sql-server-减少SQL Server中基于行的连续行之间的差异

我对SQL Server有一个疑问:如何计算当前行与上一行之间的分钟差?

样本数据:表step1:

CREATE TABLE [dbo].[step1]
(
    [Emp ID] [float] NULL,
    [time] [datetime] NULL,
    [gr] [int] NOT NULL,
    [group_] [int] NULL
) ON [PRIMARY]
GO

INSERT [dbo].[step1] ([Emp ID], [time], [gr], [group_]) 
VALUES (1, CAST(N'2017-08-02T09:00:00.000' AS DateTime), 1, 1),
       (1, CAST(N'2017-08-02T10:30:00.000' AS DateTime), 0, 1),
       (1, CAST(N'2017-08-02T11:00:00.000' AS DateTime), 0, 1),
       (1, CAST(N'2017-08-02T12:00:00.000' AS DateTime), 0, 1),
       (1, CAST(N'2017-08-02T13:00:00.000' AS DateTime), 0, 1),
       (1, CAST(N'2017-08-03T06:30:00.000' AS DateTime), 1, 2),
       (1, CAST(N'2017-08-03T08:30:00.000' AS DateTime), 0, 2),
       (1, CAST(N'2017-08-03T09:30:00.000' AS DateTime), 0, 2),
       (1, CAST(N'2017-08-03T12:30:00.000' AS DateTime), 0, 2),
       (1, CAST(N'2017-08-03T12:40:00.000' AS DateTime), 0, 2),
       (1, CAST(N'2017-08-03T17:10:00.000' AS DateTime), 0, 2),
       (1, CAST(N'2017-08-05T23:30:00.000' AS DateTime), 1, 3),
       (1, CAST(N'2017-08-06T01:55:00.000' AS DateTime), 0, 3),
       (1, CAST(N'2017-08-06T02:15:00.000' AS DateTime), 0, 3),
       (1, CAST(N'2017-08-06T06:10:00.000' AS DateTime), 0, 3),
       (1, CAST(N'2017-08-06T14:01:00.000' AS DateTime), 1, 4),
       (1, CAST(N'2017-08-06T15:01:00.000' AS DateTime), 0, 4),
       (1, CAST(N'2017-08-06T15:20:00.000' AS DateTime), 0, 4),
       (1, CAST(N'2017-08-06T20:01:00.000' AS DateTime), 0, 4),
       (5, CAST(N'2017-08-02T23:30:00.000' AS DateTime), 1, 1),
       (5, CAST(N'2017-08-03T01:30:00.000' AS DateTime), 0, 1),
       (5, CAST(N'2017-08-03T01:40:00.000' AS DateTime), 0, 1),
       (5, CAST(N'2017-08-03T04:00:00.000' AS DateTime), 0, 1),
       (5, CAST(N'2017-08-03T04:30:00.000' AS DateTime), 0, 1),
       (5, CAST(N'2017-08-03T06:00:00.000' AS DateTime), 0, 1);

基于上述数据,我希望输出如下:

Emp ID | Time                    | gr | group_ | diffminutes
-------+-------------------------+----+--------+-------------
    1  | 2017-08-02 09:00:00.000 | 1  |   1    |  90
    1  | 2017-08-02 10:30:00.000 | 0  |   1    |  30
    1  | 2017-08-02 11:00:00.000 | 0  |   1    |  60
    1  | 2017-08-02 12:00:00.000 | 0  |   1    |  60
    1  | 2017-08-02 13:00:00.000 | 0  |   1    | NULL
    1  | 2017-08-03 06:30:00.000 | 1  |   2    | 120
    1  | 2017-08-03 08:30:00.000 | 0  |   2    |  60
    1  | 2017-08-03 09:30:00.000 | 0  |   2    | 180
    1  | 2017-08-03 12:30:00.000 | 0  |   2    |  10
    1  | 2017-08-03 12:40:00.000 | 0  |   2    | 270
    1  | 2017-08-03 17:10:00.000 | 0  |   2    | NULL
    1  | 2017-08-05 23:30:00.000 | 1  |   3    | 145
    1  | 2017-08-06 01:55:00.000 | 0  |   3    |  20
    1  | 2017-08-06 02:15:00.000 | 0  |   3    | 235
    1  | 2017-08-06 06:10:00.000 | 0  |   3    | NULL
    1  | 2017-08-06 14:01:00.000 | 1  |   4    |  60
    1  | 2017-08-06 15:01:00.000 | 0  |   4    |  19
    1  | 2017-08-06 15:20:00.000 | 0  |   4    | 281
    1  | 2017-08-06 20:01:00.000 | 0  |   4    | NULL
    5  | 2017-08-02 23:30:00.000 | 1  |   1    | 120
    5  | 2017-08-03 01:30:00.000 | 0  |   1    |  10
    5  | 2017-08-03 01:40:00.000 | 0  |   1    | 140
    5  | 2017-08-03 04:00:00.000 | 0  |   1    |  30
    5  | 2017-08-03 04:30:00.000 | 0  |   1    |  90
    5  | 2017-08-03 06:00:00.000 | 0  |   1    | NULL

我试过像下面的查询:

select 
    a.[Emp ID], a.Time,
    datediff(mi, a.Time, b.Time) diffminutes 
from 
    (select  
         *, 
         row_number() over (partition by [Emp ID], group_ order by time) as rn 
     from 
         step1) a
left join 
    (select  
         *, 
         row_number() over (partition by [Emp ID], group_ order by time) as rn 
     from 
         step1) b on a.[Emp ID] = b.[Emp ID] 
                  and a.rn = b.rn + 1
order by 
    a.Time

但它没有返回预期的结果.

您能告诉我如何在SQL Server中完成此任务吗?

最佳答案
对于SQL Server 2008,请尝试以下操作:

;with cte as
(select *,ROW_NUMBER() OVER (PARTITION BY GROUP_ ORDER BY [time]) as rownumber
 from step1 

 )
 select c1.* ,abs(datediff(minute,c2.[time],c1.[time]))
 from cte c1
 left join
 cte c2
 on c1.[emp id]=c2.[emp id]
 and c1.group_=c2.group_
 and c1.rownumber+1=c2.rownumber
 order by c1.[emp id],c1.[time] 

从SQL Server 2012版本开始,这变得更加简单:

select 
    *,
    abs(datediff(minute,
        lead([time]) over (partition by [emp id], group_ order by [time]), time)) as diff
from step1

转载注明原文:sql-server-减少SQL Server中基于行的连续行之间的差异 - 代码日志