这是我保存在MS SQL数据库中的DTR设备
ID | Employee_ID | Date | InOutMode
-------+-------------+---------------------+-----------
70821 | 104 | 2019-10-11 19:00:00 | 0
70850 | 104 | 2019-10-12 07:01:00 | 1
如果我要分离输入和输出,它应该像这样:
ID | Employee_ID | IN | OUT
-------+-------------+---------------------+-----------
70821 | 104 | 2019-10-11 19:00:00 | 2019-10-12 07:01:00
发生的情况是,我不知道我的查询是否有错。超时不是2019-10-12而是2019-10-11与TIME-IN一样,它看起来像这样:
ID | Employee_ID | IN | OUT
-------+-------------+---------------------+-----------
70821 | 104 | 2019-10-11 19:00:00 | 2019-10-11 07:01:00
尝试一下,
DECLARE @Temp_Table Table
(
Empoyee_id int,
[Date] datetime,
[InOutMode] bit
)
INSERT INTO @Temp_Table
(
Empoyee_id,[Date],[InOutMode]
)
SELECT 104,'20191011 09:30',1
UNION ALL
SELECT 104,'20191011 19:30',0
UNION ALL
SELECT 104,'20191012 09:30',1
UNION ALL
SELECT 104,'20191012 12:30',0
UNION ALL
SELECT 104,'20191012 19:00',0
UNION ALL
SELECT 104,'20191013 09:30',1
UNION ALL
SELECT 104,'20191013 07:30',0
UNION ALL
SELECT 104,'20191014 09:30',1
SELECT Empoyee_id,[Date],[In],IIF([In]>[Out],null,[Out]) as [Out]
FROM
(
SELECT Empoyee_id,CAST([Date] AS DATE) AS [Date],
MIN(IIF(InOutMode=1,[Date],NULL)) AS [In] ,
MAX(IIF(InOutMode=0,[Date],NULL)) AS [Out]
FROM @Temp_Table
GROUP BY Empoyee_id,CAST([Date] AS DATE)
)A
尝试一下:
;
WITH Ins as (
Select *
FROM HR_DTR_Device
WHERE InOutMode = 0
),
Outs as (
Select *
FROM HR_DTR_Device
WHERE InOutMode = 1
)
SELECT Ins.ID,
Ins.Employee_ID,
Ins.Date as [In]
(
SELECT Min(Outs.Date)
FROM Outs
WHERE Ins.Employee_ID = Outs.Employee_ID
AND Outs.Date > Ins.Date
) as [Out]
FROM Ins
WHERE Ins.Employee_ID = '104'
这是什么:
Ins
和Outs
分开,就好像它们是分开的数据源一样。实际上,使用Common Table Expressions可以预定义子查询并为其命名。Ins
中的每个记录,从Outs
中查找仍大于In
日期的最小日期。 (这假设您的记录是完整的,并且您永远不可能连续有两个Ins
,因为有人忘记了退出。)Out
日期何时发生没有任何假设,只是它比In
日期晚(根据定义)。这样,您不必担心员工是在当天晚些时候还是第二天早些时候离开(如果您有不同工作班次的员工。)我认为您的大错误在这里:
(SELECT MAX(Date) FROM HR_DTR_Device XX
WHERE InOutMode = 1
AND XX.Employee_ID = AA.Employee_ID
AND CAST(XX.Date AS DATE) = CAST(AA.Date AS DATE)) AS 'Out'
您将返回该雇员在同一日历日期(并且是Out
)的最大日期。但是,如果员工工作到第二天早上,则日期将已更改!
您可以通过将测试更改为此来解决此问题:
CAST(DATEADD(d, -1, XX.Date) AS DATE) = CAST(AA.Date AS DATE)
...但是它仅适用于通宵工作的员工,而我的解决方案只是查找员工上班后下一次下班的时间,而不管是在同一天,第二天还是下一周!
如果您喜欢此解决方案,请将其标记为您接受的解决方案。谢谢。
这是我保存在MS SQL数据库中的DTR设备