【问题标题】:Calculate time difference for records in SQL Server计算 SQL Server 中记录的时间差
【发布时间】:2023-03-14 01:20:01
【问题描述】:

我有一个名为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 数据库。

提前致谢。

【问题讨论】:

  • 你能添加预期的输出吗
  • 解析描述以获取分配的组...那会很难看
  • @user4473935 您能否通过单击here 将预期输出包含为编辑
  • 你用的是哪个版本的sql server?
  • 您的输出日期戳与表数据不匹配

标签: sql sql-server time


【解决方案1】:

我想这就是你要找的东西:

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 将两个连续的行放在同一行上,然后能够减去两个日期之间的时间差。

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

【讨论】:

  • 上面的脚本似乎有些问题。我无法编译/运行它。第 5 行显示错误。我的实际表名是 ACTPROBM1。此表不包含任何列,如 Duration。我们需要动态计算持续时间并将其显示为别名列。
  • @user4473935 再试一次,我修改了查询。我注意到额外的Duration 列并将其删除。使用当前查询。
【解决方案2】:

用你的表名替换@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)

【讨论】:

  • 如果数字和类型的相同组合以后重复,脚本将失败。
  • @Sourav_Agasti 是的,但我希望这个数字描述它所属的组。这意味着该组将永远不会重复。类型与我的脚本无关
【解决方案3】:

下面的脚本可以得到你想要的。

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

【讨论】:

    【解决方案4】:

    不是很接近,但这样的东西应该可以工作

    架构

    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 查询

    ;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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-13
      • 2021-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多