微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从数据手指中选择先进先出时间不同的日期

如何解决从数据手指中选择先进先出时间不同的日期

这是我的数据手指表[dbo]。[tFPLog]

CardID  Date        Time   TransactionCode
100     2020-09-01  08:00  IN
100     2020-09-01  17:00  OUT 
100     2020-09-01  17:10  OUT 
200     2020-09-01  16:00  IN
200     2020-09-02  02:00  OUT
200     2020-09-02  02:15  OUT
100     2020-09-02  07:00  IN
100     2020-09-02  16:00  OUT
200     2020-09-02  09:55  IN
200     2020-09-02  10:00  IN
200     2020-09-02  21:00  OUT

条件

  1. 假设员工将在同一天/第二天进出。
  2. 假设员工在同一天/第二天会有多个输入和输出。因此需要先入后出
  3. 持续时间=(FirstInTime-LastOutTime)

我使用查询得到的当前结果:

WITH CTE AS(
SELECT CardID,[Date] AS DateIn,MIN(CASE TransactionCode WHEN 'In' THEN [time] ELSE '23:59:59.999' END) AS TimeIn,--'23:59:59.999' as we are after the MIN,and NULL is the lowest value
       [Date] AS DateOut,MAX(CASE TransactionCode WHEN 'Out' THEN [time] END) AS TimeOut
FROM YourTable
GROUP BY CardID,[Date])
SELECT C.DateIn,C.TimeIn,C.DateOut,C.TimeOut,DATEADD(MINUTE,DATEDIFF(MINUTE,C.TimeOut),CONVERT(time(0),'00:00:00')) AS Duration
FROM CTE C;

===== 当前结果 =====

CardID  DateIN      TimeIN  DateOUT     TimeOUT  Duration
100     2020-09-01  08:00   2020-09-01  17:10    09:10
200     2020-09-01  16:00   ?           ?        ?
100     2020-09-02  07:00   2020-09-02  16:00    09:00
200     2020-09-02  09:55   2020-09-02  21:00    11:05

===== 需要的结果 ===== 我想要这个结果。

CardID  DateIN      TimeIN  DateOUT     TimeOUT  Duration
100     2020-09-01  08:00   2020-09-01  17:10    09:10
200     2020-09-01  16:00   2020-09-02  02:15    10:15
100     2020-09-02  07:00   2020-09-02  16:00    09:00
200     2020-09-02  09:55   2020-09-02  21:00    11:05

如何获取第二天的DateOUT和TimeOUT?条件为FirsT IN和LAST OUT。请帮忙,谢谢您。

解决方法

这似乎使您真的使问题变得过于复杂。只需使用一些条件聚合,然后在几分钟内就可以得到差异:

WITH CTE AS(
    SELECT CardID,[Date] AS DateIn,MIN(CASE TransactionCode WHEN 'In' THEN [time] ELSE '23:59:59.999' END) AS TimeIn,--'23:59:59.999' as we are after the MIN,and NULL is the lowest value
           [Date] AS DateOut,MAX(CASE TransactionCode WHEN 'Out' THEN [time] END) AS TimeOut
    FROM YourTable
    GROUP BY CardID,[Date])
SELECT C.DateIn,C.TimeIn,C.DateOut,C.TimeOut,DATEADD(MINUTE,DATEDIFF(MINUTE,C.TimeOut),CONVERT(time(0),'00:00:00')) AS Duration
FROM CTE C;

假定 [date]date,而[time]time(因为毕竟这就是它们的名称...)。

侧面注意:似乎有些多余的DateInDateOut列始终具有相同的值。也可能只有一个[Date]列。


或者,也许您实际上在此之后?

WITH CTE AS(
    SELECT CardID,[Time] AS TimeIn,LEAD([Date]) OVER (PARTITION BY CardID ORDER BY [Date],[Time]) AS DateOut,LEAD([Time]) OVER (PARTITION BY CardID ORDER BY [Date],[Time]) AS TimeOut,TransactionCode
    FROM dbo.YourTable)
SELECT C.DateIn,C.TimeOut
FROM CTE C
WHERE TransactionCode = 'IN';

请注意,在这种情况下,最好将[date][time]的值作为datetime / datetime2存储在单列中,而不是分开的因为这些值显然彼此不同。


基于(希望)最终目标的帖子:

WITH VTE AS(
    SELECT *
    FROM (VALUES(100,CONVERT(date,'20200901'),'08:00:00'),'IN'),(100,'17:00:00'),'OUT'),'17:10:00'),(200,'16:00:00'),'20200902'),'02:00:00'),'02:15:00'),'07:00:00'),'09:55:00'),'10:00:00'),'21:00:00'),'OUT'))V(CardID,[Date],[Time],TransactionCode)),Changes AS(
    SELECT CardID,'00:00:00',[time]),CONVERT(datetime2(0),[date])) AS Dt2,--Way easier to work with later
           TransactionCode,CASE TransactionCode WHEN LEAD(TransactionCode) OVER (PARTITION BY CardID ORDER BY [Date],[Time]) THEN 0 ELSE 1 END AS CodeChange
    FROM VTE V),Groups AS(
    SELECT CardID,dt2,TransactionCode,ISNULL(SUM(CodeChange) OVER (PARTITION BY CardID ORDER BY dt2 ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS Grp
    FROM Changes),MinMax AS(
    SELECT CardID,CASE TransactionCode WHEN 'IN' THEN MIN(dt2) WHEN 'Out' THEN MAX(dt2) END AS GrpDt2
    FROM Groups
    GROUP BY CardID,Grp),--And now original Logic
CTE AS(
    SELECT CardID,GrpDt2 AS DatetimeIn,LEAD([GrpDt2]) OVER (PARTITION BY CardID ORDER BY GrpDt2) AS DateTimeOut,TransactionCode
    FROM MinMax)
SELECT C.CardID,DatetimeIn) AS DateIn,DatetimeIn) AS TimeIn,DatetimeOut) AS DateOtt,DatetimeOut) AS TimeOut,DatetimeIn,DateTimeOut),'00:00:00')) AS Duration
FROM CTE C
WHERE TransactionCode = 'IN';

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。