重叠跨度

时间:2015-05-29 20:23:40

标签: sql sql-server-2008-r2 overlapping

我正在尝试编写一个查询,以便针对特定跨度重新排序日期范围。它应该做一些看起来像这样的事情

Row   Rank   Begin Date   End Date
1     B      3/24/13      11/1/13
2     A      10/30/13     4/9/15
3     B      3/26/15      12/31/15

让它变成

Row   Rank   Begin Date   End Date
1     B      3/24/13      10/29/13
2     A      10/30/13     4/9/15
3     B      4/10/15      12/31/15

为了进一步解释,第2行中的日期排名更高(A> B),因此第1行和第3行中的日期必须围绕第2行中的日期进行更改,以避免日期重叠。

我正在使用SQL Server 2008 R2

2 个答案:

答案 0 :(得分:0)

请使用以下查询更新表格。

Update table_name 
set End_Date = DATEADD(day, -1, select Begin_Date from Table_name where   
Row_number = '2')
where row = 1;

每次运行查询时都需要更改行号。让我知道如果这适合你。

我建议先创建一个视图

CREATE OR REPLACE VIEW tempview AS
SELECT row, begin_date FROM table_name
WHERE row > 1;

然后使用此查询更新所有行。如果不能仅更新第一行。

Update table_name 
set End_Date = DATEADD(day, -1, select Begin_Date from tempview)

希望这有效

答案 1 :(得分:0)

您可以使用以下查询:

;WITH CTE AS (
   SELECT Row, Rank, BeginDate, EndDate,
          ROW_NUMBER() OVER (ORDER BY BeginDate) AS rn
   FROM mytable
), ToUpdate AS (
   SELECT c1.Row, c1.Rank, c1.BeginDate, c1.EndDate,
          c2.Rank AS pRank, c2.EndDate AS pEndDate, 
          c3.Rank AS nRank, c3.BeginDate AS nBeginDate
   FROM CTE AS c1
   LEFT JOIN CTE AS c2 ON c1.rn = c2.rn + 1
   LEFT JOIN CTE AS c3 ON c1.rn = c3.rn - 1
   WHERE c1.Rank = 'B'
)
UPDATE ToUpdate
SET BeginDate = CASE 
                   WHEN pEndDate IS NULL 
                      THEN BeginDate
                   WHEN (pEndDate >= BeginDate) AND (pRank = 'A') 
                      THEN DATEADD(d, 1, pEndDate)
                   ELSE BeginDate
                END,
    EndDate = CASE 
                   WHEN nBeginDate IS NULL 
                      THEN EndDate
                   WHEN (nBeginDate <= EndDate) AND (nRank = 'A') 
                      THEN DATEADD(d, -1, nBeginDate)
                   ELSE EndDate
                END 

最初构建CTE以将连续的升序编号分配给表的每个记录。 ROW_NUMBER()窗口函数用于此目的。

使用此CTE作为基础,我们构建ToUpdate。后者CTE包含当前的日期值以及上一个下一个记录。 这LEFT JOIN

LEFT JOIN CTE AS c2 ON c1.rn = c2.rn + 1

用于与之前的记录连接在一起,而这一个:

LEFT JOIN CTE AS c3 ON c1.rn = c3.rn - 1

用于与 next 记录一起加入。

使用CASE表达式,我们现在可以轻松识别重叠,如果有,则执行更新。

Demo here