考勤SQL语句

时间:2018-04-13 18:22:58

标签: sql

9:20到16:30之间的时间检查,并在当天21:00到下一个日期的凌晨3:00之间检查,这是表格

select * 
from checkinout

输出:

USERID            CHECKTIME
-----------------------------------------
64                2018-03-02 13:04:26.000
64                2018-03-03 01:11:38.000
64                2018-03-03 13:14:01.000
64                2018-03-04 01:44:10.000
64                2018-03-04 13:29:40.000

用户ID 64在2018-03-02 13:04:26.000办理登机手续,并在第二天2018-03-03 01:11:38.000退房,这是我需要的表格

UserID   checkdate      Checkin         Checkout        workhour
----------------------------------------------------------------------------------
64       2018-03-02     13:04:26.000    01:11:38.000    =13:04:26.000-01:11:38.000
64       2018-03-03     13:14:01.000    01:44:10.000    =13:14:01.000-01:44:10.000

如何从我的表格中获得此输出?

3 个答案:

答案 0 :(得分:0)

你去吧

select userid,  max(cast(checkin as date)) checkdate, 
max(CONVERT(VARCHAR(8),checkin,108)) checkin, max(CONVERT(VARCHAR(8),checkout,108)) checkout,
max(CONVERT(VARCHAR(8),checkin,108))+'-'+max(CONVERT(VARCHAR(8),checkout,108))workhour
from
(select userid, cast(checktime as date) checkdate, checktime,
case when row_number() over(order by cast(checktime as date), checktime) % 2 = 1 
then 'Checkin' 
else 'Checkout' end [Action],
case when row_number() over(order by cast(checktime as date), checktime) % 2 = 1 
then row_number() over(order by cast(checktime as date), checktime)
else row_number() over(order by cast(checktime as date), checktime)-1
end Visit
from #checkinout)a
pivot (min(checktime) for [action] in ([Checkin], [Checkout])) a 
group by userid, visit 

答案 1 :(得分:0)

我认为这会让你进入球场。这将使用您在评论中添加的有关如何识别“检入时间”和“检出时间”的信息,而不是依据按日期排序时依赖记录的顺序。

SELECT CheckIn.Userid, 
    Cast(CheckIn.CheckInTime as Date) as CheckDate, 
    CONVERT(VARCHAR(8),CheckIn.CheckInTime,108) as CheckIn,
    CONVERT(VARCHAR(8),CheckOut.CheckOutTime,108) as CheckOut,
    DATEDIFF(hh,CheckIn.CheckInTime, CheckOut.CheckOutTime) as hours
From
    (       
        SELECT
            ROW_NUMBER() OVER (PARTITION BY userid ORDER BY checktime) as checkid,
            Checktime as CheckInTime,
            Userid
        From Checkinout
        WHERE CAST(CheckTime as Time) BETWEEN '09:14:00' AND '16:30:00'     
    )CheckIn
    INNER JOIN
    (
        SELECT
            ROW_NUMBER() OVER (PARTITION BY userid ORDER BY checktime) as checkid,
            CheckTime as CheckOutTime
            Userid
            WHERE CAST(CheckTime as Time) BETWEEN '21:00:00' AND '24:00:00' 
                OR  CAST(CheckTime as Time) BETWEEN '00:00:00' AND '03:00:00'
        From Checkinout
    )CheckOut
    ON CheckIn.CheckID = CheckOut.CheckId

这仍然可能有点粗略,因为我们仍然依赖CheckIn,CheckOut,CheckIn,CheckOut这样的顺序没有任何偏差,但是......再次......球场肯定。

答案 2 :(得分:0)

这是我的方法

示例数据

--sample data
if object_id('tempdb..#checkinout') is not null drop table #checkinout
CREATE TABLE #checkinout(userid int, checktime DATETIME)
INSERT INTO #checkinout(userid,checktime) VALUES
(64,                '2018-03-02 13:04:26.000'),
(64,              '2018-03-03 01:11:38.000'),
(64,                '2018-03-03 13:14:01.000'),
(64,                '2018-03-04 01:44:10.000'),
(64,                '2018-03-04 13:29:40.000')

下面的查询 - 只需将#checkinout替换为您的表格,它应该可以正常工作。

--query, get some sorting in place
if object_id('tempdb..#x') is not null drop table #x
SELECT c.userid,
        c.checktime,
       ROW_NUMBER() OVER(PARTITION BY c.userid ORDER BY c.checktime) AS 'Sorted'
INTO #x 
FROM #checkinout AS c --replace with your table, and everything should work


--label the rows by checkin or checkout
if object_id('tempdb..#y') is not null drop table #y
SELECT x.*,
       CASE WHEN x.Sorted % 2 <> 0 THEN 'Checkin' ELSE 'Checkout' END  AS 'Type'
INTO #y
FROM #x AS x


--get data into format desired
SELECT cin.userid,
       CAST(cin.checktime AS DATE) AS 'CheckDate',
       CAST(cin.checktime AS TIME) AS 'Checkin',
       CAST(cout.checktime AS TIME) AS 'Checkout',
       DATEDIFF(HOUR, cin.checktime, cout.checktime) AS 'Hours'
FROM #y AS cin
     outer APPLY
     (
        SELECT y.checktime 
        FROM #y AS y
        WHERE y.userid=cin.userid AND y.Type='Checkout' AND y.Sorted=cin.Sorted+1
     ) AS cout
WHERE cin.Type='Checkin' AND cout.checktime IS NOT null

输出

userid  CheckDate   Checkin             Checkout           Hours
64      2018-03-02  13:04:26.0000000    01:11:38.0000000    12
64      2018-03-03  13:14:01.0000000    01:44:10.0000000    12