从下一行动态创建新的日期字段

时间:2010-07-29 17:52:44

标签: sql sql-server sql-server-2005

我有一张数据表。我有一个显示日期的字段。我已将此列设置为“开始日期”。我想创建一个额外的列作为结束日期,其中结束日期将是下一行的开始日期。您能否通过获取下一行中的开始日期数据来查询创建结束日期的信息?

6 个答案:

答案 0 :(得分:2)

首先,你必须提出“订单”的定义,因为表中的行没有任何顺序存储。

当您知道订单是什么时,您可以创建一个存储过程:

insert into the_table (new_id, start_date) values (@id, @start_date);

update the_table
set end_date = @start_date
where id = <the id determined by your sorting rule>;

答案 1 :(得分:2)

我假设您目前拥有包含

等值的行
StartDate
---------
1 Jan 1990
2 June 1998
4 September 2006

你想改成

StartDate              EndDate
---------              ------------
1 Jan 1990             2 June 1998
2 June 1998            4 September 2006
4 September 2006       NULL

除了冗余和维护问题之外,这个问题让我想起了this question这些带有相关列的设置在查询数据时实际上导致了原始海报问题。 (在这个问题上我更喜欢Unreason's answer!)

为什么需要添加EndDate列?它可能会提出一个没有它的查询。

编辑在对row_number()进行了大量讨论之后,我实际上找不到一个比这更好的计划的查询。 (假设StartDate上的索引)

SELECT 
        id,
        StartDate, 
           (SELECT MIN(StartDate) 
            FROM  testTable t2 
            WHERE t2.StartDate > t1.StartDate) AS EndDate
FROM testTable t1

答案 2 :(得分:1)

取决于“下一行”的意思。

您是否可以提供样本数据集,并指定如何确定行的顺序?

修改

您的记录顺序确实很重要 - 您将不得不确定它是什么。现在,我正在假设通过start_date对它进行排序是可以接受的。

--GET the first relevant start date
declare @start datetime
set @start = select MIN(start_date) from table

declare @end datetime
set @end = @start

WHILE @end is not null

  --GET the next relevant end date
  SET @end = select MIN(start_date) from table where start_date > @start

  --Update the table with the end date
  UPDATE table
  SET end_date = @end
  WHERE start_date = @start

  --GET the next relevant start date
  SET @start = @end

END

答案 3 :(得分:1)

假设您已经拥有自己的列并且拥有自动递增主键:

Update T1
Set T1.EndDate = T2.StartDate
From [Table] T1
Inner Join [Table] T2 on T1.Id = T2.Id - 1

答案 4 :(得分:0)

最后一行怎么样?对于那个endDate将是空白的吗?

答案 5 :(得分:0)

我正在回答这个问题,因为它正在其他地方引用。

取决于id没有洞是危险的。 identity列可能存在当前接受的答案未考虑的差距。

在SQL Server 2012+中,答案只是lag()。在早期版本中,您可以使用cross apply

Update T1
    Set T1.EndDate = T2.StartDate
    From [Table] T1 cross apply
         (select top 1 t2.*
          from [Table] T2 
          where t2.StartDate > t1.Startdate
          order by t2.StartDate asc
         ) t2;

使用table(StartDate)上的索引,这甚至可能具有合理的效果。