SQL Server,计算每天多次休息的总小时数

SQL Server,计算每天多次休息的总小时数,sql,sql-server,Sql,Sql Server,我正在创建一个查询,以获取某个人一天内经过的总小时数,但是每天的时间可能会有多次中断 这是我目前的疑问 SELECT CHINA_VISION_DorEvents.DorCtrls_Ref, CHINA_VISION_PubCards.CardCode, CHINA_VISION_DorEvents.EventTM FROM CHINA_VISION_PubCards INNER JOIN CHINA_VISION_DorEvents

我正在创建一个查询,以获取某个人一天内经过的总小时数,但是每天的时间可能会有多次中断

这是我目前的疑问

SELECT     
   CHINA_VISION_DorEvents.DorCtrls_Ref, 
   CHINA_VISION_PubCards.CardCode, 
   CHINA_VISION_DorEvents.EventTM
FROM       
   CHINA_VISION_PubCards 
INNER JOIN
   CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
WHERE     
   (CHINA_VISION_PubCards.CardCode = '000006f1') 
   AND CHINA_VISION_DorEvents.DorCtrls_Ref = '16'
ORDER BY
   CONVERT(Date,CHINA_VISION_DorEvents.EventTM) DESC
此查询当前不尝试计算经过的时间,但以下是查询结果,以便您可以查看数据的外观

Ref CardCode          EventTM
---------------------------------------
16  000006f1    2015-01-27 07:32:35.000
16  000006f1    2015-01-26 07:38:02.000
16  000006f1    2015-01-26 12:30:54.000
16  000006f1    2015-01-26 13:03:28.000
16  000006f1    2015-01-26 17:28:47.000
16  000006f1    2015-01-23 07:31:10.000
16  000006f1    2015-01-23 12:22:50.000
16  000006f1    2015-01-23 12:47:51.000
16  000006f1    2015-01-23 17:00:20.000
16  000006f1    2015-01-22 07:35:03.000
16  000006f1    2015-01-22 12:28:13.000
16  000006f1    2015-01-22 13:03:12.000
16  000006f1    2015-01-22 16:55:56.000
正如您所看到的,大多数日子有4条记录,我需要计算出它们的运行时间,例如26条记录

07:38:02
12:30:54
elapsed time = 4 hours, 52 minutes and 52 seconds
13:03:28
17:28:47
Elapsed time = 4 hours, 25 minutes and 19 seconds
因此,26日的总时间为9小时17分钟71

所以结果看起来

 Date     Elapsed
 2015-01-26   9:17:71
等等

我们不需要计算2-3之间的值,因为用户未在此登录

                         1   2        3         4
think of it like this   ON - OFF    BACK ON  - OFF
表结构

 Name            type         allow null
 Reference          int         Unchecked
 DorCtrls_Ref       int         Checked
 EventsID           tinyint     Checked
 EventTM            datetime    Checked
 CardCode           varchar(50) Checked
 JustificationCode  tinyint     Checked
 RecordIndex        bigint      Checked
 Memo               varchar(50) Checked
 TempltCard         varchar(1024)Checked
 Templtlength        varchar(32)Checked
 TempltDir          varchar(50) Checked 

我自己还没能测试这个,但它可能会给你一个好的开始。如果您想将光标保存在SQL中,我会使用光标,尽管我可能更喜欢在CLR中使用光标。其他人可能有更好的方法,但您可以尝试以下方法:

Declare @olddate datetime,
    @date datetime
DECLARE @Table table (Ref int, CardCode varchar(20), EventTM datetime, ElapsedTime varchar(30))

Declare cur_mycursor Cursor fast_forward for

SELECT     CHINA_VISION_DorEvents.EventTM
FROM       CHINA_VISION_PubCards INNER JOIN
CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
WHERE     (CHINA_VISION_PubCards.CardCode = '000006f1') 
and      CHINA_VISION_DorEvents.DorCtrls_Ref= '16'
Order by CHINA_VISION_DorEvents.EventTM desc

Open cur_mycursor
Fetch next from cur_mycursor into @olddate

While @@FETCH_STATUS = 0
Begin
Fetch next from cur_mycursor into @date
INSERT INTO @Table (Ref, CardCode, EventTM, ElapsedTime)
SELECT     CHINA_VISION_DorEvents.DorCtrls_Ref, 
   CHINA_VISION_PubCards.CardCode, 
   CHINA_VISION_DorEvents.EventTM,
   case when Convert(varchar, @date, 112) = Convert(varchar, CHINA_VISION_DorEvents.EventTM, 112) 
        then Cast(datediff(mi, @date, CHINA_VISION_DorEvents.EventTM) / 1440 as varchar) + ' days ' +
             Cast(datediff(mi, @date, CHINA_VISION_DorEvents.EventTM) % 1440 / 60 as varchar) + ' hours ' +
             Cast(datediff(mi, @date, CHINA_VISION_DorEvents.EventTM) % 1440 %60 as varchar) + ' minutes'
        else '0'
    end as elapsedtime
FROM       CHINA_VISION_PubCards INNER JOIN
   CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
WHERE     (CHINA_VISION_PubCards.CardCode = '000006f1') 
and      CHINA_VISION_DorEvents.DorCtrls_Ref= '16' and CHINA_VISION_DorEvents.EventTM = @olddate
Order by CHINA_VISION_DorEvents.EventTM desc
Set @olddate = @date
end
close cur_mycursor

Select * from @Table order by EventTM asc

deallocate cur_mycursor

我自己还没能测试这个,但它可能会给你一个好的开始。如果您想将光标保存在SQL中,我会使用光标,尽管我可能更喜欢在CLR中使用光标。其他人可能有更好的方法,但您可以尝试以下方法:

Declare @olddate datetime,
    @date datetime
DECLARE @Table table (Ref int, CardCode varchar(20), EventTM datetime, ElapsedTime varchar(30))

Declare cur_mycursor Cursor fast_forward for

SELECT     CHINA_VISION_DorEvents.EventTM
FROM       CHINA_VISION_PubCards INNER JOIN
CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
WHERE     (CHINA_VISION_PubCards.CardCode = '000006f1') 
and      CHINA_VISION_DorEvents.DorCtrls_Ref= '16'
Order by CHINA_VISION_DorEvents.EventTM desc

Open cur_mycursor
Fetch next from cur_mycursor into @olddate

While @@FETCH_STATUS = 0
Begin
Fetch next from cur_mycursor into @date
INSERT INTO @Table (Ref, CardCode, EventTM, ElapsedTime)
SELECT     CHINA_VISION_DorEvents.DorCtrls_Ref, 
   CHINA_VISION_PubCards.CardCode, 
   CHINA_VISION_DorEvents.EventTM,
   case when Convert(varchar, @date, 112) = Convert(varchar, CHINA_VISION_DorEvents.EventTM, 112) 
        then Cast(datediff(mi, @date, CHINA_VISION_DorEvents.EventTM) / 1440 as varchar) + ' days ' +
             Cast(datediff(mi, @date, CHINA_VISION_DorEvents.EventTM) % 1440 / 60 as varchar) + ' hours ' +
             Cast(datediff(mi, @date, CHINA_VISION_DorEvents.EventTM) % 1440 %60 as varchar) + ' minutes'
        else '0'
    end as elapsedtime
FROM       CHINA_VISION_PubCards INNER JOIN
   CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
WHERE     (CHINA_VISION_PubCards.CardCode = '000006f1') 
and      CHINA_VISION_DorEvents.DorCtrls_Ref= '16' and CHINA_VISION_DorEvents.EventTM = @olddate
Order by CHINA_VISION_DorEvents.EventTM desc
Set @olddate = @date
end
close cur_mycursor

Select * from @Table order by EventTM asc

deallocate cur_mycursor

根据您在问题中发布的结果,您可以尝试以下代码

CREATE TABLE #TEMP(Ref INT,CardCode VARCHAR(40),EventTM DATETIME)

INSERT INTO #TEMP
SELECT 16,  '000006f1',    '2015-01-27 07:32:35.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 07:38:02.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 12:30:54.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 13:03:28.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 17:28:47.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 07:31:10.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:22:50.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:47:51.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 17:00:20.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 07:35:03.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 12:28:13.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 13:03:12.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 16:55:56.000'
;WITH CTE AS
(
    -- Gets row number  Order the date
    SELECT ROW_NUMBER() OVER( ORDER BY CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM))RNO,  
           CHINA_VISION_DorEvents.DorCtrls_Ref Ref, 
           CHINA_VISION_PubCards.CardCode, 
           CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM) EventTM
    FROM   CHINA_VISION_PubCards INNER JOIN
           CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
    WHERE  (CHINA_VISION_PubCards.CardCode = '000006f1') 
     and   CHINA_VISION_DorEvents.DorCtrls_Ref= '16'
)
,CTE2 AS
(
    -- Split to hours,minutes and seconds
    SELECT C1.*,C2.EventTM EM,DATEDIFF(S,C1.EventTM,C2.EventTM)DD,
    cast(
        (cast(cast(C2.EventTM as float) - cast(C1.EventTM as float) as int) * 24) 
        + datepart(hh, C2.EventTM - C1.EventTM)
        as INT)HH
    ,CAST(right('0' + cast(datepart(mi, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)MM 
    ,CAST(right('0' + cast(datepart(ss, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)SS    
    FROM CTE C1
    LEFT JOIN CTE C2 ON C1.RNO=C2.RNO-1
    WHERE C1.RNO % 2 <> 0
),
CTE3 AS
(
    -- Sum the hours, minute and seconds
    SELECT CAST(EventTM AS DATE)EventTM,
    SUM(HH) HH,SUM(MM) MM,SUM(SS) SS
    FROM CTE2
    GROUP BY CAST(EventTM AS DATE)
)
-- Format the elapsed time
SELECT EventTM,
CASE WHEN MM >=60 THEN CAST(HH+1 AS VARCHAR(10)) END + ':' +
CASE WHEN MM >=60 THEN right('0' + CAST(MM-60 AS VARCHAR(10)),2) END + ':' + 
CAST(SS  AS VARCHAR(10))Elapsed
FROM CTE3
质疑

查看结果 编辑:

从您的查询中,您可以使用以下代码

CREATE TABLE #TEMP(Ref INT,CardCode VARCHAR(40),EventTM DATETIME)

INSERT INTO #TEMP
SELECT 16,  '000006f1',    '2015-01-27 07:32:35.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 07:38:02.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 12:30:54.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 13:03:28.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 17:28:47.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 07:31:10.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:22:50.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:47:51.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 17:00:20.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 07:35:03.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 12:28:13.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 13:03:12.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 16:55:56.000'
;WITH CTE AS
(
    -- Gets row number  Order the date
    SELECT ROW_NUMBER() OVER( ORDER BY CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM))RNO,  
           CHINA_VISION_DorEvents.DorCtrls_Ref Ref, 
           CHINA_VISION_PubCards.CardCode, 
           CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM) EventTM
    FROM   CHINA_VISION_PubCards INNER JOIN
           CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
    WHERE  (CHINA_VISION_PubCards.CardCode = '000006f1') 
     and   CHINA_VISION_DorEvents.DorCtrls_Ref= '16'
)
,CTE2 AS
(
    -- Split to hours,minutes and seconds
    SELECT C1.*,C2.EventTM EM,DATEDIFF(S,C1.EventTM,C2.EventTM)DD,
    cast(
        (cast(cast(C2.EventTM as float) - cast(C1.EventTM as float) as int) * 24) 
        + datepart(hh, C2.EventTM - C1.EventTM)
        as INT)HH
    ,CAST(right('0' + cast(datepart(mi, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)MM 
    ,CAST(right('0' + cast(datepart(ss, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)SS    
    FROM CTE C1
    LEFT JOIN CTE C2 ON C1.RNO=C2.RNO-1
    WHERE C1.RNO % 2 <> 0
),
CTE3 AS
(
    -- Sum the hours, minute and seconds
    SELECT CAST(EventTM AS DATE)EventTM,
    SUM(HH) HH,SUM(MM) MM,SUM(SS) SS
    FROM CTE2
    GROUP BY CAST(EventTM AS DATE)
)
-- Format the elapsed time
SELECT EventTM,
CASE WHEN MM >=60 THEN CAST(HH+1 AS VARCHAR(10)) END + ':' +
CASE WHEN MM >=60 THEN right('0' + CAST(MM-60 AS VARCHAR(10)),2) END + ':' + 
CAST(SS  AS VARCHAR(10))Elapsed
FROM CTE3

根据您在问题中发布的结果,您可以尝试以下代码

CREATE TABLE #TEMP(Ref INT,CardCode VARCHAR(40),EventTM DATETIME)

INSERT INTO #TEMP
SELECT 16,  '000006f1',    '2015-01-27 07:32:35.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 07:38:02.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 12:30:54.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 13:03:28.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 17:28:47.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 07:31:10.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:22:50.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:47:51.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 17:00:20.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 07:35:03.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 12:28:13.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 13:03:12.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 16:55:56.000'
;WITH CTE AS
(
    -- Gets row number  Order the date
    SELECT ROW_NUMBER() OVER( ORDER BY CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM))RNO,  
           CHINA_VISION_DorEvents.DorCtrls_Ref Ref, 
           CHINA_VISION_PubCards.CardCode, 
           CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM) EventTM
    FROM   CHINA_VISION_PubCards INNER JOIN
           CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
    WHERE  (CHINA_VISION_PubCards.CardCode = '000006f1') 
     and   CHINA_VISION_DorEvents.DorCtrls_Ref= '16'
)
,CTE2 AS
(
    -- Split to hours,minutes and seconds
    SELECT C1.*,C2.EventTM EM,DATEDIFF(S,C1.EventTM,C2.EventTM)DD,
    cast(
        (cast(cast(C2.EventTM as float) - cast(C1.EventTM as float) as int) * 24) 
        + datepart(hh, C2.EventTM - C1.EventTM)
        as INT)HH
    ,CAST(right('0' + cast(datepart(mi, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)MM 
    ,CAST(right('0' + cast(datepart(ss, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)SS    
    FROM CTE C1
    LEFT JOIN CTE C2 ON C1.RNO=C2.RNO-1
    WHERE C1.RNO % 2 <> 0
),
CTE3 AS
(
    -- Sum the hours, minute and seconds
    SELECT CAST(EventTM AS DATE)EventTM,
    SUM(HH) HH,SUM(MM) MM,SUM(SS) SS
    FROM CTE2
    GROUP BY CAST(EventTM AS DATE)
)
-- Format the elapsed time
SELECT EventTM,
CASE WHEN MM >=60 THEN CAST(HH+1 AS VARCHAR(10)) END + ':' +
CASE WHEN MM >=60 THEN right('0' + CAST(MM-60 AS VARCHAR(10)),2) END + ':' + 
CAST(SS  AS VARCHAR(10))Elapsed
FROM CTE3
质疑

查看结果 编辑:

从您的查询中,您可以使用以下代码

CREATE TABLE #TEMP(Ref INT,CardCode VARCHAR(40),EventTM DATETIME)

INSERT INTO #TEMP
SELECT 16,  '000006f1',    '2015-01-27 07:32:35.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 07:38:02.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 12:30:54.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 13:03:28.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-26 17:28:47.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 07:31:10.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:22:50.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 12:47:51.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-23 17:00:20.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 07:35:03.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 12:28:13.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 13:03:12.000'
UNION ALL
SELECT 16,  '000006f1',    '2015-01-22 16:55:56.000'
;WITH CTE AS
(
    -- Gets row number  Order the date
    SELECT ROW_NUMBER() OVER( ORDER BY CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM))RNO,  
           CHINA_VISION_DorEvents.DorCtrls_Ref Ref, 
           CHINA_VISION_PubCards.CardCode, 
           CONVERT(DateTime,CHINA_VISION_DorEvents.EventTM) EventTM
    FROM   CHINA_VISION_PubCards INNER JOIN
           CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode
    WHERE  (CHINA_VISION_PubCards.CardCode = '000006f1') 
     and   CHINA_VISION_DorEvents.DorCtrls_Ref= '16'
)
,CTE2 AS
(
    -- Split to hours,minutes and seconds
    SELECT C1.*,C2.EventTM EM,DATEDIFF(S,C1.EventTM,C2.EventTM)DD,
    cast(
        (cast(cast(C2.EventTM as float) - cast(C1.EventTM as float) as int) * 24) 
        + datepart(hh, C2.EventTM - C1.EventTM)
        as INT)HH
    ,CAST(right('0' + cast(datepart(mi, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)MM 
    ,CAST(right('0' + cast(datepart(ss, C2.EventTM - C1.EventTM) as varchar(2)), 2)AS INT)SS    
    FROM CTE C1
    LEFT JOIN CTE C2 ON C1.RNO=C2.RNO-1
    WHERE C1.RNO % 2 <> 0
),
CTE3 AS
(
    -- Sum the hours, minute and seconds
    SELECT CAST(EventTM AS DATE)EventTM,
    SUM(HH) HH,SUM(MM) MM,SUM(SS) SS
    FROM CTE2
    GROUP BY CAST(EventTM AS DATE)
)
-- Format the elapsed time
SELECT EventTM,
CASE WHEN MM >=60 THEN CAST(HH+1 AS VARCHAR(10)) END + ':' +
CASE WHEN MM >=60 THEN right('0' + CAST(MM-60 AS VARCHAR(10)),2) END + ':' + 
CAST(SS  AS VARCHAR(10))Elapsed
FROM CTE3

如果您没有使用非常旧版本的SQL Server,这将适用于您:

测试数据:

CREATE TABLE Test(Ref int, CardCode varchar(20), EventTM datetime)
insert into Test
select 16,'000006f1','2015-01-27T07:32:35.000' union all
select 16,'000006f1','2015-01-26T07:38:02.000' union all
select 16,'000006f1','2015-01-26T12:30:54.000' union all
select 16,'000006f1','2015-01-26T13:03:28.000' union all
select 16,'000006f1','2015-01-26T17:28:47.000' union all
select 16,'000006f1','2015-01-23T07:31:10.000' union all
select 16,'000006f1','2015-01-23T12:22:50.000' union all
select 16,'000006f1','2015-01-23T12:47:51.000' union all
select 16,'000006f1','2015-01-23T17:00:20.000' union all
select 16,'000006f1','2015-01-22T07:35:03.000' union all
select 16,'000006f1','2015-01-22T12:28:13.000' union all
select 16,'000006f1','2015-01-22T13:03:12.000' union all
select 16,'000006f1','2015-01-22T16:55:56.000';
查询:

WITH ByDays AS ( -- Number the entry register in each day
SELECT 
    EventTm AS T,
    CONVERT(VARCHAR(10),EventTm,102) AS Day,
    FLOOR(CONVERT(FLOAT,EventTm)) DayNumber,
    ROW_NUMBER() OVER(PARTITION BY FLOOR(CONVERT(FLOAT,EventTm)) ORDER BY EventTm) InDay 
FROM Test
)
--SELECT * FROM ByDays ORDER BY T
,Diffs AS (
SELECT 
    E.Day,
    E.T ET, O.T OT, O.T-E.T Diff, 
    DATEDIFF(S,E.T,O.T) DiffSeconds -- difference in seconds
FROM 
    (SELECT BE.T, BE.Day, BE.InDay 
     FROM ByDays BE 
     WHERE BE.InDay % 2 = 1) E -- Even rows
INNER JOIN
    (SELECT BO.T, BO.Day, BO.InDay 
     FROM ByDays BO 
     WHERE BO.InDay % 2 = 0) O -- Odd rows
ON E.InDay + 1 = O.InDay -- Join rows (1,2), (3,4) and so on
   AND E.Day = O.Day --  in the same day
)
--SELECT * FROM Diffs

SELECT Day, 
    SUM(DiffSeconds) Seconds, 
    CONVERT(VARCHAR(8), 
    (DATEADD(S, SUM(DiffSeconds), '1900-01-01T00:00:00')),
    108) TotalHHMMSS -- The same, formatted as HH:MM:SS
FROM Diffs GROUP BY Day
结果是这样的

Day         Seconds  TotalHHMMSS
2015.01.22  31554    08:45:54
2015.01.23  32649    09:04:09
2015.01.26  33491    09:18:11

请参阅相应的sql FIDLE:

如果您没有使用非常旧的sql Server版本,这将适用于您:

测试数据:

CREATE TABLE Test(Ref int, CardCode varchar(20), EventTM datetime)
insert into Test
select 16,'000006f1','2015-01-27T07:32:35.000' union all
select 16,'000006f1','2015-01-26T07:38:02.000' union all
select 16,'000006f1','2015-01-26T12:30:54.000' union all
select 16,'000006f1','2015-01-26T13:03:28.000' union all
select 16,'000006f1','2015-01-26T17:28:47.000' union all
select 16,'000006f1','2015-01-23T07:31:10.000' union all
select 16,'000006f1','2015-01-23T12:22:50.000' union all
select 16,'000006f1','2015-01-23T12:47:51.000' union all
select 16,'000006f1','2015-01-23T17:00:20.000' union all
select 16,'000006f1','2015-01-22T07:35:03.000' union all
select 16,'000006f1','2015-01-22T12:28:13.000' union all
select 16,'000006f1','2015-01-22T13:03:12.000' union all
select 16,'000006f1','2015-01-22T16:55:56.000';
查询:

WITH ByDays AS ( -- Number the entry register in each day
SELECT 
    EventTm AS T,
    CONVERT(VARCHAR(10),EventTm,102) AS Day,
    FLOOR(CONVERT(FLOAT,EventTm)) DayNumber,
    ROW_NUMBER() OVER(PARTITION BY FLOOR(CONVERT(FLOAT,EventTm)) ORDER BY EventTm) InDay 
FROM Test
)
--SELECT * FROM ByDays ORDER BY T
,Diffs AS (
SELECT 
    E.Day,
    E.T ET, O.T OT, O.T-E.T Diff, 
    DATEDIFF(S,E.T,O.T) DiffSeconds -- difference in seconds
FROM 
    (SELECT BE.T, BE.Day, BE.InDay 
     FROM ByDays BE 
     WHERE BE.InDay % 2 = 1) E -- Even rows
INNER JOIN
    (SELECT BO.T, BO.Day, BO.InDay 
     FROM ByDays BO 
     WHERE BO.InDay % 2 = 0) O -- Odd rows
ON E.InDay + 1 = O.InDay -- Join rows (1,2), (3,4) and so on
   AND E.Day = O.Day --  in the same day
)
--SELECT * FROM Diffs

SELECT Day, 
    SUM(DiffSeconds) Seconds, 
    CONVERT(VARCHAR(8), 
    (DATEADD(S, SUM(DiffSeconds), '1900-01-01T00:00:00')),
    108) TotalHHMMSS -- The same, formatted as HH:MM:SS
FROM Diffs GROUP BY Day
结果是这样的

Day         Seconds  TotalHHMMSS
2015.01.22  31554    08:45:54
2015.01.23  32649    09:04:09
2015.01.26  33491    09:18:11

请参阅相应的sql FIDLE:

试试这个,输出是正确的

your output is wrong.9:17:71 is wrong.it should be 9:18:11.

    Declare @t table(Ref int, CardCode varchar(20), EventTM datetime)
insert into @t
select  16,'000006f1','2015-01-27 07:32:35.000' union all
select  16,'  000006f1','2015-01-26 07:38:02.000' union all
select 16,'  000006f1','2015-01-26 12:30:54.000' union all
select 16,'  000006f1','2015-01-26 13:03:28.000' union all
select 16,'  000006f1','2015-01-26 17:28:47.000' union all
select 16,'  000006f1','2015-01-23 07:31:10.000' union all
select 16,'  000006f1','2015-01-23 12:22:50.000' union all
select 16,'  000006f1','2015-01-23 12:47:51.000' union all
select 16,'  000006f1','2015-01-23 17:00:20.000' union all
select 16,'  000006f1','2015-01-22 07:35:03.000' union all
select 16,'  000006f1','2015-01-22 12:28:13.000' union all
select 16,'  000006f1','2015-01-22 13:03:12.000' union all
select 16,'  000006f1','2015-01-22 16:55:56.000'

;with CTE as
(
select *,row_number()over(partition by dateadd(d,0,datediff(d,0,EventTM)) 
order by EventTM)rn  from @t 
)
,CTE1 as
(
select Ref,CardCode,EventTM, rn oddrn,0 TimeElapse from CTE where rn%2<>0
union all
select a.Ref,a.CardCode,a.EventTM, rn ,datediff(s,b.EventTM,a.EventTM) 
from CTE a
inner join CTE1 b on 
dateadd(d,0,datediff(d,0,a.EventTM))= dateadd(d,0,datediff(d,0,b.EventTM)) 
and a.ref=b.ref
and a.rn-b.oddrn=1 and a.rn%2=0
)

select EventTM,cast((convert(varchar(5),TimeElapse/3600) +':'+ 
convert(varchar(5),TimeElapse%3600/60) 
+':'+ convert(varchar(5),TimeElapse%60)) as datetime)  from 
(select dateadd(d,0,datediff(d,0,EventTM)) EventTM,sum(TimeElapse) TimeElapse 
from cte1 
where TimeElapse>0
group by dateadd(d,0,datediff(d,0,EventTM)))tbl

试试这个,输出是正确的

your output is wrong.9:17:71 is wrong.it should be 9:18:11.

    Declare @t table(Ref int, CardCode varchar(20), EventTM datetime)
insert into @t
select  16,'000006f1','2015-01-27 07:32:35.000' union all
select  16,'  000006f1','2015-01-26 07:38:02.000' union all
select 16,'  000006f1','2015-01-26 12:30:54.000' union all
select 16,'  000006f1','2015-01-26 13:03:28.000' union all
select 16,'  000006f1','2015-01-26 17:28:47.000' union all
select 16,'  000006f1','2015-01-23 07:31:10.000' union all
select 16,'  000006f1','2015-01-23 12:22:50.000' union all
select 16,'  000006f1','2015-01-23 12:47:51.000' union all
select 16,'  000006f1','2015-01-23 17:00:20.000' union all
select 16,'  000006f1','2015-01-22 07:35:03.000' union all
select 16,'  000006f1','2015-01-22 12:28:13.000' union all
select 16,'  000006f1','2015-01-22 13:03:12.000' union all
select 16,'  000006f1','2015-01-22 16:55:56.000'

;with CTE as
(
select *,row_number()over(partition by dateadd(d,0,datediff(d,0,EventTM)) 
order by EventTM)rn  from @t 
)
,CTE1 as
(
select Ref,CardCode,EventTM, rn oddrn,0 TimeElapse from CTE where rn%2<>0
union all
select a.Ref,a.CardCode,a.EventTM, rn ,datediff(s,b.EventTM,a.EventTM) 
from CTE a
inner join CTE1 b on 
dateadd(d,0,datediff(d,0,a.EventTM))= dateadd(d,0,datediff(d,0,b.EventTM)) 
and a.ref=b.ref
and a.rn-b.oddrn=1 and a.rn%2=0
)

select EventTM,cast((convert(varchar(5),TimeElapse/3600) +':'+ 
convert(varchar(5),TimeElapse%3600/60) 
+':'+ convert(varchar(5),TimeElapse%60)) as datetime)  from 
(select dateadd(d,0,datediff(d,0,EventTM)) EventTM,sum(TimeElapse) TimeElapse 
from cte1 
where TimeElapse>0
group by dateadd(d,0,datediff(d,0,EventTM)))tbl


可能值得一看。你没有完全解释。26日有4个日期你计算在1&2和3&4之间。为什么你没有计算在2&3之间。回复。因为2到3之间的时间这个人没有工作,所以这样想需要计算时间没有工作需要计算开-关返回-关闭您使用的SQL Server版本?输出9:17:71错误,应该是9:18:11。检查我的最新查询。它很短。可能值得一看。您没有完全解释。26日有4个日期您计算在1和2到3和4之间。为什么您没有计算在2和4之间3.回复。由于时间介于2和3之间,因此该人员没有工作。这样想需要计算时间没有工作需要计算开-关返回开-关您使用的是哪个SQL Server版本?输出9:17:71错误,应该是9:18:11。检查我的最新查询。它非常简短。您好,感谢您的回复,我对SQL和查询中的许多内容不太了解,但是我马上就收到了错误消息102,级别15,状态1,第14行“下一步”附近的语法错误。Msg 102,级别15,状态1,第18行“下一步”附近的语法不正确。我刚刚尝试了修复程序,现在查询运行,但是它正在执行我以前从未见过的操作@Josh Kirkpatrick lol,再次道歉,也许编辑过的会更好?这次我得到的是返回的,0行受影响0行受影响0行受影响0行受影响0行受影响反复使用游标当一个操作可以通过批处理操作完成时不是最好的主意。它通常有一个性能的打击。请参阅其他建议的解决方案。您好,感谢您的回复,我对SQL和此查询中的许多内容不太了解,但我立即收到错误消息102,级别15,状态1,第14行“下一步”附近的语法不正确。Msg 102,级别15,状态1,第18行“下一步”附近的语法不正确。我刚刚尝试了修复程序,现在查询运行,但是它正在执行我以前从未见过的操作@Josh Kirkpatrick lol,再次道歉,也许编辑过的会更好?这次我得到的是返回的,0行受影响0行受影响0行受影响0行受影响0行受影响反复使用游标当一个操作可以通过批处理操作完成时不是最好的主意。它通常有一个性能的打击。请看其他建议的解决方案。您好,谢谢您的回复,似乎效果不错,但由于某些原因,日期没有排序,例如,这里是前10个结果2010-02-02 7:92:3152 2013-04-15 2:31:7402 2013-01-22 1:96:7978 2010-04-26 7:94:2423 2009-11-11 6:62:2127 2012-10-31 1:32:8459 2013-10-15 3:74:7062 2014-09-18 2:52:6515 2010-07-18 14:26-619 2012-08-09 1:78:

8121正如你所看到的,日子到处都是,你知道为什么吗?在你得到我的查询结果后,你是在告诉我订单的情况吗@Josh KirkpatrickYes这是结果输入简单的顺序。在最后一行添加ORDER BY EventTM@Josh KirkpatrickHi,运行编辑版本,我得到了26日的结果2015-01-23 63:02:43,我假设这相当于那天的63小时。。。。并运行另一个版本。收到我2015-01-23 2:29:6892我假设是2.29小时,我们知道我们应该期待9:03:69这样的结果嗨,谢谢你的回复,似乎效果很好,但由于某些原因,日期没有排序,例如,这里是前10个结果2010-02-02 7:92:3152 2013-04-15 2:31:7402 2013-01-22 1:96:7978 2010-04-26 7:94:2423 2009-11-11 6:62:2127 2012-10-31 1:32:8459 2013-10-15 3:74:7062 2014-09-18 2:52:6515 2010-07-18 14:619 2012-08-09 1:78:8121,如您所见这一天到处都是,你知道为什么吗?在你得到我的查询结果后,你是在告诉我订单的情况吗@Josh KirkpatrickYes这是结果输入简单的顺序。在最后一行添加ORDER BY EventTM@Josh KirkpatrickHi,运行编辑版本,我得到了26日的结果2015-01-23 63:02:43,我假设这相当于那天的63小时。。。。并运行另一个版本。获取我2015-01-23 2:29:6892,我假设是2.29小时,我们知道我们应该预期的结果是9:03:69嗨,sql server正在运行2008,当我使用我的表而不是test运行此操作时,我收到此错误,Msg 207,级别16,状态1,第3行无效列名“T”。Msg 207,16级,状态1,第4行无效列名“T”。Msg 207,16级,状态1,第5行无效列名“T”。Msg 207,级别16,状态1,第5行列名“T”无效。此查询的结果不正确,例如2015.01.23 39832 11:03:52我们预计结果接近9.18小时。我已更新查询,以便它使用与原始查询类似的结构。注意,在一些测试之后,我再次修改了查询。由于我将日期转换为整数的方式,日期分组不起作用,现在问题解决了。现在您得到了预期的结果。你可以看到,第27天只有一行,所以我被丢弃了。嗨,我刚刚运行了更新版本,我仍然得到了与预期不符的结果,2015.01.23 41175 11:26:15是结果,但我们预计在9.18小时左右会有结果,有什么想法吗?@Josh Kirkpatrick在第23天说,这是数字:12:22:50-07:31:10=04:51:40和17:00:20-12:47:51=04:12:29。如果你把04:51:40+04:12:29加起来,你得到的正好是08:63:69,即08:64:09,即09:04:09。因此,它工作正常,请仔细检查。您好,sql server正在运行2008,当我使用我的表而不是test运行此操作时,出现此错误,Msg 207,级别16,状态1,第3行无效列名“T”。Msg 207,16级,状态1,第4行无效列名“T”。Msg 207,16级,状态1,第5行无效列名“T”。Msg 207,级别16,状态1,第5行列名“T”无效。此查询的结果不正确,例如2015.01.23 39832 11:03:52我们预计结果接近9.18小时。我已更新查询,以便它使用与原始查询类似的结构。注意,在一些测试之后,我再次修改了查询。由于我将日期转换为整数的方式,日期分组不起作用,现在问题解决了。现在您得到了预期的结果。你可以看到,第27天只有一行,所以我被丢弃了。嗨,我刚刚运行了更新版本,我仍然得到了与预期不符的结果,2015.01.23 41175 11:26:15是结果,但我们预计在9.18小时左右会有结果,有什么想法吗?@Josh Kirkpatrick在第23天说,这是数字:12:22:50-07:31:10=04:51:40和17:00:20-12:47:51=04:12:29。如果你把04:51:40+04:12:29加起来,你得到的正好是08:63:69,即08:64:09,即09:04:09。所以它工作正常,请仔细检查。您好,我尝试了这个版本,查询已经运行了6分钟多,到目前为止还没有结果,所以我不确定这里发生了什么,不知道它在不到一秒钟内给了我输出。只需准确地复制粘贴并运行。我使用的是sql server 2008。或者您一定被误认为是其他脚本。您好,我尝试了这个版本,查询已经运行了6分钟多,到目前为止还没有结果,所以我不确定这里发生了什么,不知道它在不到一秒钟的时间内给了我输出。只需准确地复制粘贴并运行即可。我使用的是sql server 2008。或者你一定被误认为是其他脚本。