计算SQL Server中记录的时间差

时间:2015-01-20 12:43:48

标签: sql sql-server time

我在下面的表名为acttable1

NUMBER TYPE           DATESTAMP            DESCRIPTION 
--------------------------------------------------------------------------------
10010  OPEN           2014-04-16 05:34:03  ASSIGNED TO GROUP 1
10010  REASSIGNMENT   2014-04-19 09:29:00  REASSIGNMENT FROM GROUP 1 TO GROUP 2
10010  REASSIGNMENT   2014-04-20 08:35:00  REASSIGNMENT FROM GROUP 2 TO GROUP 3
10010  CLOSED         2014-04-20 10:15:33  CLOSED

我需要计算总时间(DATESTAMP列)中的每个值与GROUP 1GROUP 2GROUP 3之间的时差。

请协助我构建SQL查询,以便我可以提取报告。

预期产出。

NUMBER  TYPE          DATESTAMP         Duration    DESCRIPTION
--------------------------------------------------------------------------------
10010   OPEN          04/19/14 00:45    00:00:00    ASSIGNED TO GROUP 1
10010   REASSIGNMENT  04/19/14 09:29    08:44:00    REASSIGNMENT FROM GROUP 1 TO GROUP 2
10010   REASSIGNMENT  04/20/14 07:29    22:00:00    REASSIGNMENT FROM GROUP 2 TO GROUP 3
10010   CLOSED        04/20/14 10:15    02:46:33    CLOSED

我正在使用MS SQL 2008数据库。

提前致谢。

4 个答案:

答案 0 :(得分:0)

我认为这就是你要找的东西:

SELECT
    Number
    , Type
    , DateStamp
   , CAST(CAST(SECONDS/60/60%24 as VARCHAR) + ':'+ 
     CAST((SECONDS/60)%60 as VARCHAR) + ':' +
     CAST(SECONDS%60 as VARCHAR) AS TIME) AS TotalTime
    , Description
FROM
    (SELECT CurrentEvent.NUMBER
        ,CurrentEvent.TYPE
        ,CurrentEvent.DATESTAMP
        ,DATEDIFF(SECOND, CurrentEvent.DATESTAMP, ISNULL(NextEvent.DATESTAMP, CurrentEvent.DateStamp)) AS SECONDS
        ,CurrentEvent.DESCRIPTION
    FROM (
        SELECT NUMBER
            ,TYPE
            ,DATESTAMP
            ,DESCRIPTION
            ,ROW_NUMBER() OVER (PARTITION BY NUMBER ORDER BY DATESTAMP) Ordering
        FROM acttable1
        ) AS CurrentEvent LEFT JOIN (
        SELECT NUMBER
            ,DATESTAMP
            ,ROW_NUMBER() OVER (PARTITION BY NUMBER ORDER BY DATESTAMP) Ordering
        FROM acttable1
        ) AS NextEvent ON CurrentEvent.Ordering + 1 = NextEvent.Ordering
    ) AS FinalResultSet

基本思路是根据DATESTAMP对结果进行排序,然后使用LEFT JOIN在同一行上连续两行,然后减去两者之间的时差日期。

在此之后,只需在最后一次查询的帮助下完成格式化,之后计算两个连续事件之间的持续时间(以秒为单位)。

答案 1 :(得分:0)

将@t替换为您的表名并尝试:

测试表和数据:

DECLARE @t table
(NUMBER int, TYPE varchar(20), DATESTAMP datetime, DESCRIPTION varchar(40))
INSERT @t values
(10010,'OPEN','2014-04-16 05:34:03','ASSIGNED TO GROUP 1'),
(10010,'REASSIGNMENT','2014-04-19 09:28:00','REASSIGNMENT FROM GROUP 1 TO GROUP 2'),
(10010,'REASSIGNMENT','2014-04-20 08:35:00','REASSIGNMENT FROM GROUP 2 TO GROUP 3'),
(10010,'CLOSED','2014-04-20 10:15:33','CLOSED')

查询:

SELECT
  NUMBER, 
  TYPE,
  DATESTAMP, 
  datestamp - (SELECT max(DATESTAMP) FROM @t 
              WHERE datestamp < t.datestamp and 
              number = t.number) AS Duration, 
  DESCRIPTION
FROM @t t

结果:

NUMBER TYPE           DATESTAMP           Duration            DESCRIPTION
10010  OPEN           2014-04-16 05:34:03                     ASSIGNED TO GROUP 1
10010  REASSIGNMENT   2014-04-19 09:28:00 1900-01-04 03:53:57 REASSIGNMENT FROM GROUP 1 TO GROUP 2
10010  REASSIGNMENT   2014-04-20 08:35:00 1900-01-01 23:07:00 REASSIGNMENT FROM GROUP 2 TO GROUP 3
10010  CLOSED         2014-04-20 10:15:33 1900-01-01 01:40:33 CLOSED

如果您愿意,可以将持续时间转换为时间:

cast( datestamp - (SELECT max(DATESTAMP) FROM @t 
              WHERE datestamp < t.datestamp and 
              number = t.number) as time)

答案 2 :(得分:0)

以下脚本可以为您提供所需的内容。

select *, case when type = 'CLOSED' THEN 3 WHEN type = 'REASSIGNMENT' then 2 WHEN TYPE = 'OPEN' THEN 1 END AS Num 
into #acttable1
from acttable1

create table #abc
(
id int identity(1,1)
,number int
,type varchar(20)
,datestamp datetime
,description varchar(100)
)
--drop table #abc 
insert into #abc
select number, type, datestamp, description from #acttable1 order by Num, datestamp

select A.*, 
CONVERT(VARCHAR(10),ISNULL(datediff(ss, B.datestamp, A.datestamp), 0)/3600) 
    +':' 
    + RIGHT('00'+CONVERT(VARCHAR(2),(ISNULL(datediff(ss, B.datestamp, A.datestamp), 0)%3600)/60),2) 
    +':' 
    + RIGHT('00'+CONVERT(VARCHAR(2),ISNULL(datediff(ss, B.datestamp, A.datestamp), 0)%60),2) AS [Duration] 
from #abc A left join #abc B on A.id - 1 = B.id

SQL FIDDLE

答案 3 :(得分:0)

不太接近,但这样的事情应该有效

<强> SCHEMA

CREATE TABLE acttable1
(
    [NUMBER] int not null,
    [TYPE] varchar(25) not null,
    [DATESTAMP] datetime not null,
    [DESCRIPTION] varchar(255) not null
);

INSERT INTO acttable1 
    ([NUMBER], [TYPE], [DATESTAMP], [DESCRIPTION])
VALUES
    (10010, 'OPEN', '2014-04-19 00:45.000', 'ASSIGNED TO GROUP 1'),
    (10010, 'REASSIGNMENT', '2014-04-19 09:29:00.000',  'REASSIGNMENT FROM GROUP 1 TO GROUP 2'),
    (10010, 'REASSIGNMENT', '2014-04-20 07:29:00.000', 'REASSIGNMENT FROM GROUP 2 TO GROUP 3'),
    (10010, 'CLOSED', '2014-04-20 10:15:33.000', 'CLOSED');

SQL QUERY

;WITH cteAssignments
AS
(
  SELECT  ROW_NUMBER() OVER(PARTITION BY [NUMBER] ORDER BY [DATESTAMP]) AS SeqNo,
          [NUMBER], 
          [TYPE], 
          [DATESTAMP], 
          [DESCRIPTION]
  FROM    acttable1    
)

SELECT 
      a1.*,
      COALESCE(CONVERT(VARCHAR(8), DATEDIFF(s, a2.[DATESTAMP], a1.[DATESTAMP])/3600) + ':' + CONVERT(VARCHAR(5), DATEDIFF(s, a2.[DATESTAMP], a1.[DATESTAMP]) % 3600/60) +':'+ CONVERT(VARCHAR(5), (DATEDIFF(s, a2.[DATESTAMP], a1.[DATESTAMP]) % 60)), '00:00:00') as Duration    
FROM cteAssignments a1
LEFT JOIN    cteAssignments a2
  ON a2.SeqNo + 1 = a1.SeqNo

将产生以下结果:

SEQNO   NUMBER  TYPE              DATESTAMP                     DESCRIPTION                             DURATION
    1   10010   OPEN              April, 19 2014 00:45:00+0000  ASSIGNED TO GROUP 1                     00:00:00
    2   10010   REASSIGNMENT      April, 19 2014 09:29:00+0000  REASSIGNMENT FROM GROUP 1 TO GROUP 2    8:44:0
    3   10010   REASSIGNMENT      April, 20 2014 07:29:00+0000  REASSIGNMENT FROM GROUP 2 TO GROUP 3    22:0:0
    4   10010   CLOSED            April, 20 2014 10:15:33+0000  CLOSED                                  2:46:33

<强> SQL Fiddle