【问题标题】:Group Sequential SQL Records分组顺序 SQL 记录
【发布时间】:2014-10-08 18:08:10
【问题描述】:

寻找一种方法将连续的时钟记录分组到一行中。

源系统有一个身份列、员工 ID、日期和进/出标志(1=in & 2=out)。请注意,

ID          EmployeeID    DATE                   InOut
1019374     5890          2008-08-19 14:07:14    1
1019495     5890          2008-08-19 18:17:08    2
1019504     5890          2008-08-19 18:50:40    1
1019601     5890          2008-08-19 22:06:18    2

我正在寻找可以给我以下结果的 sql

EmployeeID ClockIn             BreakStart          BreakEnd            ClockOut
5890       2008-08-19 14:07:14 2008-08-19 18:17:08 2008-08-19 18:50:40 2008-08-19 22:06:18

请注意,由于时钟编辑,源系统中的 ID 并不总是连续的。日期应按时间顺序排列。如果只存在两个打卡,我将需要在没有休息的情况下填充打卡和打卡日期(或者我可以使用案例语句提取的一致内容)。下面没有中断示例:

EmployeeID ClockIn             BreakStart          BreakEnd            ClockOut
5890       2008-08-19 14:07:14                                         2008-08-19 22:06:18

Sql版本是2008 R2

在此先感谢,我不知道如何使其始终如一地工作,非常感谢您的帮助。

【问题讨论】:

  • 如果时钟输入和输出多于 2 个怎么办?
  • 好点,我需要某种错误/手动审查标志。

标签: sql sql-server date time


【解决方案1】:

您可以使用ROW_NUMBER() 函数和窗口化COUNT() 来处理无休息日:

;with cte as (SELECT *,ROW_NUMBER() OVER(PARTITION BY EmployeeID, CAST(dt AS DATE) ORDER BY dt) RN
                      ,COUNT(*) OVER(PARTITION BY EmployeeID, CAST(dt AS DATE)) Dt_CT
              FROM Table1)
SELECT EmployeeID
      ,Dt = CAST(dt AS DATE)
      ,ClockIn = MAX(CASE WHEN RN = 1 THEN DT END)
      ,BreakStart =  MAX(CASE WHEN Dt_CT = 4 AND RN = 2 THEN DT END)
      ,BreakEnd =  MAX(CASE WHEN Dt_CT = 4 AND RN = 3 THEN DT END)
      ,ClockOut = MAX(CASE WHEN (Dt_CT = 2 AND RN = 2) OR RN = 4 THEN DT END)
FROM cte
GROUP BY EmployeeID
        ,CAST(dt AS DATE)

演示:SQL Fiddle

这是按天设置的,因此午夜后打卡将不起作用,而且奇数出拳也会有问题,但对于像您的示例这样的简单世界来说,这将是可行的。

【讨论】:

  • 你能看到只使用视图的方法吗?
  • 你可以把这个查询放在一个视图中:CREATE VIEW Blah AS WITH ...
  • 就其价值而言,我认为这不是完成这项工作的好方法。您正在针对非错误情况进行优化,但如果出拳异常,一切都会被炸成碎片。这是应用级的业务规则编程,我觉得已经够复杂了,不应该在数据层做。
  • @ErikE 我们没有足够的知识来做出这个决定,如果它只是一个愚蠢的打卡时钟,它会在一张桌子上填满问题,那么你是对的,但我已经使用过生产的打卡系统非常干净的数据,例如晚上 11:59:59 自动打卡和午夜后有人打卡时在上午 12:00 打卡。您的观点是有效的,这可能不属于数据层。
猜你喜欢
  • 2016-08-07
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多