【问题标题】:Selecting Data from Normalized Tables从规范化表中选择数据
【发布时间】:2021-01-12 06:51:05
【问题描述】:

我一直在努力写这个查询,我想我今晚的大脑有点炸了。我有这张表可以存储一个人执行某个操作(打卡、打卡、午餐、午餐回来)的时间,并且我需要返回最后一个操作不是时钟输出的人的所有主 ID 的列表 - 但是问题是它需要稍微快一点的查询。

表结构:

ID | person_id | status | datetime | shift_type

ID = 此表的主键

person_id = 如果他们的状态不等于clock_out,我想返回的ID

状态 = 时钟输入、午餐开始、午餐结束、休息开始、休息结束、时钟输出

datetime = 添加记录的时间

shift_type = 不重要

我之前执行此查询的方式是查找在特定时间段内仍在打卡的人,但是我需要此查询来定位任何时间点。我正在尝试的查询占用了成千上万条记录,并且速度太慢了。

【问题讨论】:

    标签: mysql sql datetime greatest-n-per-group window-functions


    【解决方案1】:

    我需要返回最后一个操作不是 clock_out 的人的所有主要 ID 的列表。

    一个选项使用窗口函数,在 MySQL 8.0 中可用:

    select id
    from (
        select t.*, row_number() over(partition by person_id order by datetime desc) rn
        from mytable t
    ) t
    where rn = 1 and status <> 'clock_out'
    

    在早期版本中,一个选项使用相关子查询:

    select id
    from mytable 
    where 
        datetime = (select max(t1.datetime) from mytable t1 where t1.personid = t.person_id)
        and status <> 'clock_out'
    

    【讨论】:

    • 我不确定托管服务器是否在 Windows 上运行
    • "SELECT" 在此位置对于此服务器版本无效,需要 FOR、LOCK、TABLE、VALUES、WITH、'('
    • @JayMason:window functions 与 Windows(操作系统)无关。但是,它们在 MySQ 中可用。仅限 8.0;你运行的是哪个版本?
    • MySQL 服务器 8.0 , MySQL Workbench 8.0 CE
    • @JayMason:好的,这样就可以了。请完全按照提供的方式运行查询。
    【解决方案2】:

    进一步查看后,这是我的解决方案 -

    SELECT * FROM (
       SELECT `status`,`person_id` FROM `timeclock` ORDER BY `datetime` DESC
    ) AS tmp_table GROUP BY `person_id`
    

    之所以可行,是因为它将所有相同的人员 ID 分组在一起,然后按日期时间对它们进行排序并选择最近的。

    【讨论】:

      猜你喜欢
      • 2010-11-20
      • 2015-12-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-06
      • 2015-09-23
      • 2015-02-15
      • 2011-01-06
      相关资源
      最近更新 更多