查询以从仅包含开始日期的列表计算开始和结束日期

STL*_*Dev 1 sql-server t-sql sql-server-2008-r2

我有以下形式的数据需要合并,以便我从两行输入数据创建一行,其中第二列是下一行减去一天的值。

我一直在努力想出一种方法来做到这一点,但没有走得太远。我希望这张图能解释这个问题:

表结构

CREATE TABLE Process(
    ProcessOrder int NOT NULL IDENTITY (1, 1),
    ProcessDate date NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

询问

SELECT ProcessOrder, ProcessDate From Process ORDER BY ProcessOrder;
Run Code Online (Sandbox Code Playgroud)

数据

ProcessOrder  ProcessDate
------------  -----------
208           2016-01-04
209           2016-01-11
210           2016-01-18
211           2016-01-25
212           2016-02-01
213           2016-02-08
Run Code Online (Sandbox Code Playgroud)

我需要将上述数据变成以下形状(注意,从后续记录来看,ProcessEnd 比 ProcessBegin 少一天):

ProcessOrder  ProcessBegin  ProcessEnd
------------  ------------  ----------
208           2016-01-04    2016-01-10
209           2016-01-11    2016-01-17
210           2016-01-18    2016-01-24
211           2016-01-25    2016-01-31
212           2016-02-01    2016-02-07
213           2016-02-08    *NULL*
Run Code Online (Sandbox Code Playgroud)

编辑

我保证 ProcessOrder 列中的值是连续的,没有缺失值。

Sco*_*t M 5

由于你是 2008 年,你还没有 LEAD 函数(我相信),所以你可以用 CTE 自己做:

WITH RankedProcess AS
(
  SELECT ProcessOrder, ProcessDate, ROW_NUMBER() OVER(ORDER BY ProcessDate) AS Seq
  FROM Process
)
SELECT P1.ProcessOrder, P1.ProcessDate AS ProcessBegin, DATEADD(day, -1, P2.ProcessDate) AS ProcessEnd
FROM RankedProcess AS P1
  LEFT OUTER JOIN RankedProcess AS P2
    ON P1.Seq = P2.Seq - 1
Run Code Online (Sandbox Code Playgroud)

在 2012 年及之后,您可以只使用 LEAD:

SELECT ProcessOrder, ProcessDate AS ProcessBegin, LEAD(DATEADD(day, -1, ProcessDate)) OVER(ORDER BY ProcessDate) AS ProcessEnd
FROM Process
Run Code Online (Sandbox Code Playgroud)

鉴于更新保证 ProcessOrder 是连续的且没有缺失值(并且我假设它们与日期的顺序相同),您可以无需使用 CTE,而只需使用 ProcessOrder 列。然而,CTE 的解决方案更为通用,我认为这仍然有用,因为我通常对数据库未强制执行的数据要求持怀疑态度。