Sql server SQL Server时间表计算

Sql server SQL Server时间表计算,sql-server,tsql,datetime,sql-server-2012,Sql Server,Tsql,Datetime,Sql Server 2012,我有一个打卡程序,输出下面的数据集RECTYP_43是(1)个输入和(2)个输出冲头。我需要一个查询来查看LOGINDATE_43和LOGINTIME_43以及RECTYPE_43并获得1和2之间的差异 我认为这比事实证明的要容易 empid_43 RECTYPE_43 LOGINDATE_43 LOGINTIME_43 ------------------------------------------------------------ 127

我有一个打卡程序,输出下面的数据集
RECTYP_43
是(1)个输入和(2)个输出冲头。我需要一个查询来查看
LOGINDATE_43
LOGINTIME_43
以及
RECTYPE_43
并获得1和2之间的差异

我认为这比事实证明的要容易

empid_43    RECTYPE_43  LOGINDATE_43            LOGINTIME_43
------------------------------------------------------------
127            1        2016-10-21 00:00:00.000     0558
127            2        2016-10-21 00:00:00.000     1430
127            2        2016-10-21 00:00:00.000     1201
127            1        2016-10-21 00:00:00.000     1228
127            1        2016-10-24 00:00:00.000     0557
127            2        2016-10-24 00:00:00.000     1200
127            1        2016-10-24 00:00:00.000     1228
127            2        2016-10-24 00:00:00.000     1430
2589           2        2016-10-21 00:00:00.000     1431
2589           1        2016-10-21 00:00:00.000     0556
2589           1        2016-10-24 00:00:00.000     0550
2589           2        2016-10-24 00:00:00.000     1431
2589           2        2016-10-24 00:00:00.000     1201
2589           1        2016-10-24 00:00:00.000     1226
69             1        2016-10-24 00:00:00.000     1229
69             2        2016-10-24 00:00:00.000     1430
69             1        2016-10-24 00:00:00.000     0555
69             2        2016-10-24 00:00:00.000     1200

您可以使用一个CTE来获取所有的打孔,然后使用一个子查询来查找该时间之后的第一个打孔

;WITH ctePunchIn AS (
    SELECT empid_43, LOGINDATE_43 AS Date_In, LOGINTIME_43 AS Time_In 
    FROM #Table1 
    WHERE [RECTYPE_43] = 1
 )

 SELECT 
    empid_43, Date_In, Time_In 
    ,(SELECT TOP 1 LOGINTIME_43 FROM #Table1 WHERE 
        (empid_43 = ctePunchIn.empid_43) 
        AND 
        (LOGINDATE_43 = ctePunchIn.Date_In)
        AND 
        (LOGINTIME_43 > ctePunchIn.Time_In) 
        AND 
        (RECTYPE_43 = 2) 
        ORDER BY empid_43, Date_In, LOGINTIME_43) AS Time_Out
FROM 
    ctePunchIn

您可以使用一个CTE来获取所有的打孔,然后使用一个子查询来查找该时间之后的第一个打孔

;WITH ctePunchIn AS (
    SELECT empid_43, LOGINDATE_43 AS Date_In, LOGINTIME_43 AS Time_In 
    FROM #Table1 
    WHERE [RECTYPE_43] = 1
 )

 SELECT 
    empid_43, Date_In, Time_In 
    ,(SELECT TOP 1 LOGINTIME_43 FROM #Table1 WHERE 
        (empid_43 = ctePunchIn.empid_43) 
        AND 
        (LOGINDATE_43 = ctePunchIn.Date_In)
        AND 
        (LOGINTIME_43 > ctePunchIn.Time_In) 
        AND 
        (RECTYPE_43 = 2) 
        ORDER BY empid_43, Date_In, LOGINTIME_43) AS Time_Out
FROM 
    ctePunchIn
如果注销时间与登录时间相同,则DazedandFuzzle的方法有效,但如果用户在不同的日期注销以登录,则该方法无效

e、 g

为了适应这种情况,您需要知道表中下一项是针对该员工的。这样,您就可以确保下一个项目也是注销事件。这将有助于捕捉某人忘记打卡的情况

扩展CTE可以提供更完整的解决方案:

WITH Data AS
(
    SELECT  empId_43,
            RecType_43,
            LoginDate_43,
            LoginTime_43,
            RowNum = ROW_NUMBER() OVER (PARTITION BY empId_43 
                                  ORDER BY LoginDate_43, LoginTime_43)
    FROM Punch
)
SELECT  PIn.empId_43 [Employee],
        PIn.LoginDate_43 [LoginDate],
        PIn.LoginTime_43 [LoginTime],
        POut.LoginDate_43 [LogoutDate],
        POut.LoginTime_43 [LogoutTime]
FROM Data PIn
    LEFT JOIN Data POut ON PIn.empId_43 = POut.empId_43
        AND POut.RecType_43 = 2
        AND POut.RowNum = PIn.RowNum + 1
WHERE PIn.RecType_43 = 1
ORDER BY PIn.empId_43, PIn.LoginDate_43, PIn.LoginTime_43;
但是,
行编号
可能效率低下。当查看一个小的子集(例如,特定的日期范围等)时,这样做是最好的。

如果注销时间与登录时间相同,则DazedAndFuzzle的方法有效,但如果用户在不同的日期注销登录,则它将不起作用

e、 g

为了适应这种情况,您需要知道表中下一项是针对该员工的。这样,您就可以确保下一个项目也是注销事件。这将有助于捕捉某人忘记打卡的情况

扩展CTE可以提供更完整的解决方案:

WITH Data AS
(
    SELECT  empId_43,
            RecType_43,
            LoginDate_43,
            LoginTime_43,
            RowNum = ROW_NUMBER() OVER (PARTITION BY empId_43 
                                  ORDER BY LoginDate_43, LoginTime_43)
    FROM Punch
)
SELECT  PIn.empId_43 [Employee],
        PIn.LoginDate_43 [LoginDate],
        PIn.LoginTime_43 [LoginTime],
        POut.LoginDate_43 [LogoutDate],
        POut.LoginTime_43 [LogoutTime]
FROM Data PIn
    LEFT JOIN Data POut ON PIn.empId_43 = POut.empId_43
        AND POut.RecType_43 = 2
        AND POut.RowNum = PIn.RowNum + 1
WHERE PIn.RecType_43 = 1
ORDER BY PIn.empId_43, PIn.LoginDate_43, PIn.LoginTime_43;

但是,
行编号
可能效率低下。在查看小子集(例如特定日期范围等)时,最好这样做。

稍微不同的方法:

select
   punchIn.empid_43,
   punchIn.login as dateTime_in,
   punchout.login as dateTime_out
from
(
    SELECT  empId_43,
            RecType_43,
            LoginDate_43,
            LoginTime_43,
            dateadd('n',right(logintime_43,2),
            dateadd('hh',left(LoginTime_43,2), 
            LoginDate_43)) as login,
            RowNum = ROW_NUMBER() OVER (PARTITION BY empId_43 
                                  ORDER BY LoginDate_43, LoginTime_43)
    FROM Punch
where rectype_43 = 1
) punchIn left outer join 
(
    SELECT  empId_43,
            RecType_43,
            LoginDate_43,
            LoginTime_43,
            dateadd('n',right(logintime_43,2),
            dateadd('hh',left(LoginTime_43,2), 
            LoginDate_43)) as login,
            RowNum = ROW_NUMBER() OVER (PARTITION BY empId_43 
                                  ORDER BY LoginDate_43, LoginTime_43)
    FROM Punch
where rectype_43 = 2
) punchOut on
punchin.empID = punchout.empID and
punchin.rownum = punchout.rownum

假设所有punchin行都有相应的punchout行

稍微不同的方法:

select
   punchIn.empid_43,
   punchIn.login as dateTime_in,
   punchout.login as dateTime_out
from
(
    SELECT  empId_43,
            RecType_43,
            LoginDate_43,
            LoginTime_43,
            dateadd('n',right(logintime_43,2),
            dateadd('hh',left(LoginTime_43,2), 
            LoginDate_43)) as login,
            RowNum = ROW_NUMBER() OVER (PARTITION BY empId_43 
                                  ORDER BY LoginDate_43, LoginTime_43)
    FROM Punch
where rectype_43 = 1
) punchIn left outer join 
(
    SELECT  empId_43,
            RecType_43,
            LoginDate_43,
            LoginTime_43,
            dateadd('n',right(logintime_43,2),
            dateadd('hh',left(LoginTime_43,2), 
            LoginDate_43)) as login,
            RowNum = ROW_NUMBER() OVER (PARTITION BY empId_43 
                                  ORDER BY LoginDate_43, LoginTime_43)
    FROM Punch
where rectype_43 = 2
) punchOut on
punchin.empID = punchout.empID and
punchin.rownum = punchout.rownum
假设所有punchin行都有对应的punchout行