我需要每天为每位员工找出时钟和时钟。它有2班,第一班从0830 - 2030开始,第二班是从2030 - 0830(第二天)。以下是我的样本记录,
Time In Time Out User
2017-06-16 07:30:00.000 2017-06-16 08:30:00.000 I0495
2017-06-16 08:30:00.000 2017-06-16 12:30:00.000 I0495
2017-06-16 13:00:00.000 2017-06-16 15:30:00.000 I0495
2017-06-16 15:30:00.000 2017-06-16 19:00:00.000 I0495
2017-06-16 20:30:00.000 2017-06-16 21:30:00.000 I0603
2017-06-16 21:30:00.000 2017-06-17 00:00:00.000 I0603
2017-06-17 00:00:00.000 2017-06-17 00:30:00.000 I0603
2017-06-17 01:30:00.000 2017-06-17 04:30:00.000 I0603
2017-06-17 05:30:00.000 2017-06-17 08:30:00.000 I0603
2017-06-17 07:30:00.000 2017-06-17 08:30:00.000 I0495
2017-06-17 08:30:00.000 2017-06-17 12:30:00.000 I0495
2017-06-17 13:00:00.000 2017-06-17 15:30:00.000 I0495
2017-06-17 15:30:00.000 2017-06-17 19:00:00.000 I0495
我尝试查询如下
Select min(tbl.timein), max(tbl.timeout), tbl.user form
(
Select timein, timeout, user from tbl where timein >= '2017-06-16
07:00:00' and timeout <= '2017-06-16 20:30:00'
union all
Select timein, timeout, user from tbl where timein >= '2017-06-16
20:60:00' and timeout <= '2017-06-17 08:30:00'
)tbl
group by tb.user
我得到的结果低于预期的结果
2017-06-16 07:30:00.000 2017-06-17 08:30:00.000 I0495
2017-06-16 20:30:00.000 2017-06-17 08:30:00.000 I0603
2017-06-17 07:30:00.000 2017-06-18 08:30:00.000 I0495
预期结果
2017-06-16 07:30:00.000 2017-06-16 19:00:00.000 I0495
2017-06-16 20:30:00.000 2017-06-17 08:30:00.000 I0603
2017-06-17 07:30:00.000 2017-06-17 19:00:00.000 I0495
知道如何做到这一点。感谢。
答案 0 :(得分:0)
一种合理的解决方法,可以知道用户在超时和下一次超时之间可以进行的最大中断。假设它是<= 2小时,你可以通过获得先前超时与每个用户当前行的时间的差异来实现。然后使用运行总和基于此分配每天的组。
select usr,timein,timeout
,sum(case when diff <=120 then 0 else 1 end) over(partition by usr order by timein) as grp
from (select t.*
,datediff(minute,lag(timeout) over(partition by usr order by timein),timein) as diff
from tbl t
) t
分配组后,每个用户和组只需要min
timein和max
超时。
select usr,min(timein),max(timeout)
from (select usr,timein,timeout
,sum(case when diff <=120 then 0 else 1 end) over(partition by usr order by timein) as grp
from (select t.*
,datediff(minute,lag(timeout) over(partition by usr order by timein),timein) as diff
from tbl t
) t
) t
group by usr,grp
答案 1 :(得分:0)
也许这可以帮助并给你一个想法。
来源:
DECLARE @T TABLE
(
TimeIn DATETIME ,
[TimeOut] DATETIME ,
[User] VARCHAR(50)
)
INSERT INTO @T
( TimeIn, TimeOut, [User] )
VALUES ( '2017-06-16 07:30:00.000', '2017-06-16 08:30:00.000', 'I0495' ),
( '2017-06-16 08:30:00.000', '2017-06-16 12:30:00.000', 'I0495' ),
( '2017-06-16 13:00:00.000', '2017-06-16 15:30:00.000', 'I0495' ),
( '2017-06-16 15:30:00.000', '2017-06-16 19:00:00.000', 'I0495' ),
( '2017-06-16 20:30:00.000', '2017-06-16 21:30:00.000', 'I0603' ),
( '2017-06-16 21:30:00.000', '2017-06-17 00:00:00.000', 'I0603' ),
( '2017-06-17 00:00:00.000', '2017-06-17 00:30:00.000', 'I0603' ),
( '2017-06-17 01:30:00.000', '2017-06-17 04:30:00.000', 'I0603' ),
( '2017-06-17 05:30:00.000', '2017-06-17 08:30:00.000', 'I0603' ),
( '2017-06-17 07:30:00.000', '2017-06-17 08:30:00.000', 'I0495' ),
( '2017-06-17 08:30:00.000', '2017-06-17 12:30:00.000', 'I0495' ),
( '2017-06-17 13:00:00.000', '2017-06-17 15:30:00.000', 'I0495' ),
( '2017-06-17 15:30:00.000', '2017-06-17 19:00:00.000', 'I0495' );
查询:
IF ( OBJECT_ID('tempdb..#tmpTbl') IS NOT NULL )
BEGIN
DROP TABLE #tmpTbl
END
CREATE TABLE #tmpTbl
(
id INT IDENTITY(1, 1)
PRIMARY KEY ,
TimeIn DATETIME ,
[TimeOut] DATETIME ,
[User] VARCHAR(50) ,
flag INT ,
[lag] INT
)
INSERT INTO #tmpTbl
( TimeIn ,
TimeOut ,
[User] ,
flag ,
lag
)
SELECT TimeIn ,
TimeOut ,
[User] ,
flag ,
LAG(flag) OVER ( ORDER BY ctr ) LAG
FROM ( SELECT * ,
IIF(CAST(TimeIn AS TIME) BETWEEN '7:00' AND '8:30', 1, IIF(CAST(TimeIn AS TIME) >= '20:30', 1, 0)) flag ,
ROW_NUMBER() OVER ( ORDER BY ( SELECT
0
) ) ctr
FROM @T
) TT
DECLARE @Lastid INT
SELECT TOP 1
@Lastid = id
FROM #tmpTbl
ORDER BY id DESC
UPDATE #tmpTbl
SET flag = 2
WHERE id = @Lastid
UPDATE #tmpTbl
SET flag = 0
WHERE lag = 1
UPDATE #tmpTbl
SET flag = 2
WHERE id IN ( SELECT previd
FROM ( SELECT flag ,
LAG(flag) OVER ( ORDER BY ID ) lag ,
LAG(id) OVER ( ORDER BY ID ) previd
FROM #tmpTbl
) T
WHERE T.flag = 1
AND T.lag = 0 );
WITH CTE
AS ( SELECT * ,
ROW_NUMBER() OVER ( ORDER BY id ) ctr
FROM #tmpTbl
WHERE flag = 1
),
CTE1
AS ( SELECT * ,
ROW_NUMBER() OVER ( ORDER BY id ) ctr
FROM #tmpTbl
WHERE flag = 2
),
CTE2
AS ( SELECT cte.TimeIn ,
cte1.TimeOut ,
cte.[user]
FROM cte
JOIN cte1 ON CTE1.ctr = CTE.ctr
)
SELECT *
FROM CTE2
结果:
TimeIn TimeOut user
----------------------- ----------------------- -------
2017-06-16 07:30:00.000 2017-06-16 19:00:00.000 I0495
2017-06-16 20:30:00.000 2017-06-17 08:30:00.000 I0603
2017-06-17 07:30:00.000 2017-06-17 19:00:00.000 I0495
(3 row(s) affected)