选择Sum HH:MM两个日期之间的时间段

时间:2017-01-05 15:00:59

标签: sql sql-server database tsql

我想知道16/11/2016 09:00>之间工作的小时数(持续时间)。 2016/12/15 17:30为了实现这一点,我需要计算两个日期之间每天工作的持续时间,然后将这些日期添加到每月工作时间。

EventTime表将包含用户每次开始工作时的时钟数据,午餐时间时钟,午餐后时钟,然后在当天结束时退出。

我设法让这一天工作了一天:

EMPLOYEE    CLOCK IN            CLOCK OUT           DURATION
Tatjana     05/01/2017 08:33    05/01/2017 13:12    04:39
Harj        05/01/2017 10:59    05/01/2017 14:20    03:20
Tomasz      05/01/2017 09:55        
John        05/01/2017 09:57        
Sam         05/01/2017 08:11    05/01/2017 14:11    05:59
Paul        05/01/2017 09:39    05/01/2017 14:05    04:26
Adrian      05/01/2017 13:59        
Sophie      05/01/2017 08:42        
Meg         05/01/2017 07:56    05/01/2017 13:10    05:14
Anna        05/01/2017 07:59    05/01/2017 12:30    04:31
Adriana     05/01/2017 07:46    05/01/2017 12:44    04:58
Jacky       05/01/2017 09:01        
Anna        05/01/2017 07:57    05/01/2017 12:29    04:32
Kelly       05/01/2017 07:56    05/01/2017 12:45    04:48
Ana         05/01/2017 07:41    05/01/2017 14:13    06:32

使用以下查询实现上述目的:

SELECT
    u.Field14_50 AS EmployeeID,
    u.Firstname,
    u.Surname,
    MIN(e.EventTime) AS [Clocked In],
    CASE 
        WHEN MAX(e.EventTime) = MIN(e.EventTime) THEN NULL
        WHEN MAX(e.EventTime) > MIN(e.EventTime) THEN MAX(e.EventTime)
    END AS [Clocked Out],
    CASE
        WHEN MAX(e.EventTime) = MIN(e.EventTime) THEN NULL
        WHEN MAX(e.EventTime) > MIN(e.EventTime) THEN FORMAT((DATEDIFF(SECOND, MIN(e.EventTime), MAX(e.EventTime)) / 3600) % 24,  '00') + ':' + FORMAT((DATEDIFF(SECOND, MIN(e.EventTime), MAX(e.EventTime)) / 60) % 60, '00')
    END AS [Duration]
FROM
    UsersEx AS u
INNER JOIN
    EventsEx AS e
ON
    u.UserID = e.UserID
WHERE
    u.Field14_50 <> ''
AND
    u.DepartmentName IN (
        'Production',
        'Finance and Administration',
        'Purchase',
        'Sales',
        'Warehouse'
    )
AND
    DAY(e.EventTime) = DAY(GETDATE())     AND     MONTH(e.EventTime) = MONTH(GETDATE())      AND     YEAR(e.EventTime) = YEAR(GETDATE())
AND
    e.PeripheralName IN ('TIME AND ATTENDANCE OFFICE (In)', 'TIME AND ATTENDANCE OFFICE (Out)')
GROUP BY
    u.Field14_50,
    u.UserID,
    u.FirstName,
    u.Surname
ORDER BY
    u.Surname ASC

我希望这很清楚。

提前致谢。

更新:06/01/2017

我可以使用以下查询:

SELECT
    u.FirstName,
    e.EventTime
FROM
    UsersEx AS u    
INNER JOIN
    EventsEx AS e
ON
    u.UserID = e.UserID
WHERE
    u.Field14_50 <> ''
AND
    e.EventTime > '2016/11/16'     AND     e.EventTime < '2016/12/16'
AND
    e.PeripheralName IN ('TIME AND ATTENDANCE OFFICE (In)', 'TIME AND ATTENDANCE OFFICE (Out)')
AND
    u.DepartmentName IN ('Finance and Administration')
ORDER BY
    u.Field14_50,
    e.EventTime
ASC

得到这个结果:

Ram 16/11/2016 09:12
Ram 16/11/2016 12:59
Ram 16/11/2016 13:39
Ram 16/11/2016 17:47
Ram 17/11/2016 09:35
Ram 17/11/2016 12:45
Ram 17/11/2016 13:11
Ram 17/11/2016 17:43
Ram 21/11/2016 09:14
Ram 21/11/2016 12:24
Ram 21/11/2016 12:53
Ram 21/11/2016 17:36
Ram 22/11/2016 09:18
Ram 22/11/2016 13:32
Ram 22/11/2016 17:45
Ram 23/11/2016 09:10
Ram 23/11/2016 13:13
Ram 23/11/2016 13:51
Ram 24/11/2016 09:10
Ram 24/11/2016 13:15
Ram 24/11/2016 13:50
Ram 24/11/2016 17:41
Ram 25/11/2016 09:12
Ram 25/11/2016 17:36
Ram 28/11/2016 09:05
Ram 28/11/2016 12:32
Ram 28/11/2016 13:12
Ram 28/11/2016 17:40
Ram 29/11/2016 09:17
Ram 29/11/2016 12:45
Ram 29/11/2016 13:16
Ram 29/11/2016 17:50
Ram 30/11/2016 09:15
Ram 30/11/2016 12:51
Ram 30/11/2016 13:55
Ram 30/11/2016 17:31
Ram 01/12/2016 09:10
Ram 01/12/2016 12:44
Ram 01/12/2016 13:12
Ram 01/12/2016 17:36
Ram 02/12/2016 09:00
Ram 02/12/2016 12:19
Ram 02/12/2016 12:51
Ram 02/12/2016 17:38
Ram 05/12/2016 09:14
Ram 05/12/2016 12:45
Ram 05/12/2016 13:28
Ram 05/12/2016 17:45
Ram 06/12/2016 09:32
Ram 06/12/2016 12:15
Ram 06/12/2016 12:49
Ram 06/12/2016 17:51
Ram 07/12/2016 09:09
Ram 07/12/2016 12:43
Ram 07/12/2016 13:22
Ram 07/12/2016 17:51
Ram 08/12/2016 09:18
Ram 08/12/2016 12:54
Ram 08/12/2016 13:16
Ram 08/12/2016 17:39
Ram 09/12/2016 09:09
Ram 09/12/2016 18:02
Ram 12/12/2016 09:20
Ram 12/12/2016 12:55
Ram 12/12/2016 13:20
Ram 12/12/2016 17:47
Ram 13/12/2016 09:13
Ram 13/12/2016 13:10
Ram 13/12/2016 13:37
Ram 13/12/2016 18:01
Ram 15/12/2016 09:07
Ram 15/12/2016 12:37
Ram 15/12/2016 13:12
Ram 15/12/2016 17:53
Yuka    16/11/2016 08:52
Yuka    16/11/2016 19:05
Yuka    17/11/2016 09:02
Yuka    17/11/2016 18:25
Yuka    18/11/2016 08:23
Yuka    18/11/2016 18:26
Yuka    21/11/2016 08:12
Yuka    21/11/2016 17:59
Yuka    22/11/2016 08:51
Yuka    22/11/2016 17:44
Yuka    23/11/2016 08:43
Yuka    23/11/2016 18:07
Yuka    24/11/2016 08:42
Yuka    24/11/2016 18:24
Yuka    25/11/2016 08:37
Yuka    25/11/2016 17:34
Yuka    28/11/2016 08:44
Yuka    28/11/2016 18:03
Yuka    29/11/2016 08:11
Yuka    29/11/2016 16:58
Yuka    12/12/2016 08:51
Yuka    12/12/2016 17:57
Yuka    13/12/2016 07:51
Yuka    13/12/2016 18:30
Yuka    14/12/2016 08:32
Yuka    14/12/2016 18:04
Yuka    15/12/2016 08:40
Yuka    15/12/2016 18:09
Duncan  16/11/2016 07:25
Duncan  16/11/2016 18:28
Duncan  17/11/2016 07:25
Duncan  17/11/2016 17:48
Duncan  18/11/2016 07:29
Duncan  21/11/2016 07:33
Duncan  21/11/2016 17:48
Duncan  22/11/2016 07:31
Duncan  22/11/2016 18:14
Duncan  23/11/2016 07:43
Duncan  24/11/2016 07:21
Duncan  25/11/2016 07:32
Duncan  28/11/2016 07:35
Duncan  28/11/2016 18:11
Duncan  29/11/2016 07:34
Duncan  30/11/2016 07:35
Duncan  30/11/2016 18:21
Duncan  01/12/2016 07:27
Duncan  01/12/2016 17:57
Duncan  02/12/2016 07:38
Duncan  05/12/2016 07:29
Duncan  05/12/2016 18:12
Duncan  06/12/2016 07:28
Duncan  06/12/2016 17:37
Duncan  07/12/2016 07:13
Duncan  07/12/2016 07:19
Duncan  07/12/2016 18:01
Duncan  08/12/2016 07:22
Duncan  08/12/2016 17:56
Duncan  09/12/2016 07:24
Duncan  09/12/2016 17:30

现在如何从该结果集中获取每个用户的MIN和MAX(如下所示)?

Employee   Clocked In         Clocked Out        Duration
Ram        16/11/2016 09:12   16/11/2016 17:47   08:35
Ram        17/11/2016 09:35   17/11/2016 17:43   08:08
... 
Ram        13/12/2016 09:13   13/12/2016 18:01   08:48
Ram        15/12/2016 09:07   15/12/2016 17:53   08:46

and so on for each employee...

1 个答案:

答案 0 :(得分:0)

将每个持续时间字段转换为,然后将其添加为 HH:MM

格式

这是一个例子:

IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
    DROP TABLE #tmp

CREATE TABLE #tmp (
    Id INT IDENTITY
    , duration VARCHAR(MAX)
    )

INSERT INTO #tmp (duration)
VALUES ('04:39')
    , ('03:20')
    , ('05:59')

SELECT 
    Sum(Left(duration, 2) * 3600 + substring(duration, 4, 2) * 60) AS seconds
    , CONVERT(VARCHAR, DATEADD(ms, (Sum(Left(duration, 2) * 3600 + substring(duration, 4, 2) * 60)) * 1000, 0), 114) AS 'seconds to HH:MM'
    --http://stackoverflow.com/questions/1262497/how-to-convert-seconds-to-hhmmss-using-t-sql
FROM #tmp

DROP TABLE #tmp

<强> RESULT

seconds     seconds to HH:MM
----------- ------------------------------
50280       13:58:00:000

(1 row(s) affected)

在您的查询中实施此解决方案的一个选项是使用 CTE 。在这种情况下,CTE看起来像这样:

;WITH Base
AS (
    SELECT u.Field14_50 AS EmployeeID
        , u.Firstname
        , u.Surname
        , MIN(e.EventTime) AS [Clocked In]
        , CASE 
            WHEN MAX(e.EventTime) = MIN(e.EventTime)
                THEN NULL
            WHEN MAX(e.EventTime) > MIN(e.EventTime)
                THEN MAX(e.EventTime)
            END AS [Clocked Out]
        , CASE 
            WHEN MAX(e.EventTime) = MIN(e.EventTime)
                THEN NULL
            WHEN MAX(e.EventTime) > MIN(e.EventTime)
                THEN FORMAT((DATEDIFF(SECOND, MIN(e.EventTime), MAX(e.EventTime)) / 3600) % 24, '00') + ':' + FORMAT((DATEDIFF(SECOND, MIN(e.EventTime), MAX(e.EventTime)) / 60) % 60, '00')
            END AS [Duration]
    FROM UsersEx AS u
        INNER JOIN EventsEx AS e
            ON u.UserID = e.UserID
    WHERE u.Field14_50 <> ''
        AND u.DepartmentName IN (
            'Production'
            , 'Finance and Administration'
            , 'Purchase'
            , 'Sales'
            , 'Warehouse'
            )
        AND DAY(e.EventTime) = DAY(GETDATE())
        AND MONTH(e.EventTime) = MONTH(GETDATE())
        AND YEAR(e.EventTime) = YEAR(GETDATE())
        AND e.PeripheralName IN (
            'TIME AND ATTENDANCE OFFICE (In)'
            , 'TIME AND ATTENDANCE OFFICE (Out)'
            )
    GROUP BY u.Field14_50
        , u.UserID
        , u.FirstName
        , u.Surname
    --ORDER BY u.Surname ASC --Don't include ORDER BY here.
    )
SELECT CONVERT(VARCHAR, DATEADD(ms, (Sum(Left(duration, 2) * 3600 + substring(duration, 4, 2) * 60)) * 1000, 0), 114) AS 'sum of hours (Duration)'
FROM Base
ORDER BY u.Surname

<强>已更新

根据您的更新,您需要使用 MIN MAX 汇总功能进行查询,但为日期<执行 GROUP BY em>转换为DATE 。有了它,您可以获得每天的最高和最低价值。

<强> CODE:

SELECT u.FirstName
    , MIN(e.EventTime) AS 'Clocked In'
    , CASE 
        WHEN MIN(e.EventTime) = MAX(e.EventTime)
            THEN NULL
        ELSE MAX(e.EventTime)
        END AS 'Clocked Out'
    , DATEDIFF(SECOND, min(e.EventTime), MAX(e.EventTime)) AS 'Duration in seconds'
    , CONVERT(VARCHAR, DATEADD(ms, DATEDIFF(SECOND, min(e.EventTime), MAX(e.EventTime)) * 1000, 0), 114) AS 'Duration'
FROM UsersEx AS u
    INNER JOIN EventsEx AS e
        ON u.UserID = e.UserID
WHERE u.Field14_50 <> ''
    AND e.EventTime > '2016/11/16'
    AND e.EventTime < '2016/12/16'
    AND e.PeripheralName IN (
        'TIME AND ATTENDANCE OFFICE (In)'
        , 'TIME AND ATTENDANCE OFFICE (Out)'
        )
    AND u.DepartmentName IN ('Finance and Administration')
GROUP BY u.FirstName
    , cast(e.EventTime AS DATE)
ORDER BY u.FirstName

然后,您只需要将秒数相加并将它们转换为我向您展示的HH:MM格式,使用 CTE 或子查询。