如何解决从数据手指中选择先进先出时间不同的日期
这是我的数据手指表[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
条件
我使用查询得到的当前结果:
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
(因为毕竟这就是它们的名称...)。
侧面注意:似乎有些多余的DateIn
和DateOut
列始终具有相同的值。也可能只有一个[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 举报,一经查实,本站将立刻删除。