在同一个表中更新下一个开始时间的结束时间

时间:2014-05-25 23:37:22

标签: sql sql-server tsql

我在SQL server中有一个表:

name varchar(10)
start_time timestamp
end_time timestamp

表中的数据如下:

John, '2014-05-26 00-00-01', null
John, '2014-05-25 15-00-01', null
Tom,  '2014-05-25 16-00-01', null
John, '2014-05-25 09-00-01', null
Tom,  '2014-05-25 03-00-01', null
..

我希望有一个SQL来更新end_time与来自同一个人的下一个start_time,更新后,结果如下:

John, '2014-05-26 00-00-01', null
John, '2014-05-25 15-00-01', '2014-05-26 00-00-01'
Tom,  '2014-05-25 16-00-01', null
John, '2014-05-25 09-00-01', '2014-05-25 15-00-01'
Tom,  '2014-05-25 03-00-01', '2014-05-25 16-00-01'

SQL中有什么简单的方法吗?我认为需要内联?

(有些想法:

update mytable t1
set t1.end_time = min(t2.start_time)
inner join mytable t2 on t1.name = t2.name where t1.start_time < t2.start_time and t1.end_time = null;

但不起作用)

2 个答案:

答案 0 :(得分:0)

以下查询使用相关子查询获取下一个开始时间(您也可以使用cross applylead()函数(如果可用)。

select t.*,
       (select top 1 t2.start_time
        from t2.name = t.name and t2.start_time > t.start_time
        order by t2.start_time asc
       ) as next_start_time
from mytable t;

SQL Server的一个非常好的功能是可更新的CTE。所以你可以在更新语句中使用它:

with toupdate as (
      select t.*,
             (select top 1 t2.start_time
              from t2.name = t.name and t2.start_time > t.start_time
              order by t2.start_time asc
             ) as next_start_time
      from mytable t
     )
update toupdate
    set end_time = next_start_time;

答案 1 :(得分:0)

这可能会对你有帮助。

DECLARE @TABLE TABLE 
        (
        NAME VARCHAR(10), 
        START_TIME DATETIME, 
        END_TIME DATETIME
        )

INSERT  INTO @TABLE (NAME,START_TIME,END_TIME) VALUES 
('JOHN', '2014-05-26 00:00:01',NULL),
('JOHN', '2014-05-25 15:00:01',NULL),
('TOM',  '2014-05-25 16:00:01',NULL),
('JOHN', '2014-05-25 09:00:01',NULL),
('TOM',  '2014-05-25 03:00:01',NULL)

UPDATE  A
SET     A.END_TIME = LU.START_TIME
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY START_TIME DESC) [ROW] 
        FROM    @TABLE
        ) A 
LEFT JOIN   (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY START_TIME DESC) [ROW] 
        FROM    @TABLE
        ) LU 
ON      A.NAME = LU.NAME 
AND     A.ROW = LU.ROW + 1

SELECT * FROM @TABLE