更新 table 以避免日期重叠

Updating a table to avoid overlapping dates

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

Member   Rank   Begin Date   End Date
2275     A      9/9/14       11/17/14
2275     B      9/26/14      3/24/15
2275     B      3/25/15      12/31/15
8983     A      9/16/13      3/10/15
8983     B      2/24/15      4/28/15
8983     A      4/28/15      12/31/15

让它变成

Member   Rank   Begin Date   End Date
2275     A      9/9/14       11/17/14
2275     B      11/18/14     3/24/15
2275     B      3/25/15      12/31/15
8983     A      9/16/13      3/10/15
8983     B      3/11/15      4/27/15
8983     A      4/28/15      12/31/15

为了进一步解释,我想更新日期。除了 A > B 之外,没有太多的排名。而且只有 A 和 B。排名 A 的日期范围应该保持不变。重叠的 B 排名日期是可以的。我担心 B 排名日期与 A 排名日期重叠。 table 非常大(约 700 个成员)并且有几个不同的成员 ID。成员 2275 的第二行(等级 B)将开始日期更改为 2015 年 11 月 18 日,以不与第一行重叠。

我正在使用 Microsoft SQL Server 2008 R2

谢谢

最新编辑:这是我在 2012 年之前所做的。我认为这不是最优雅的解决方案。

WITH a AS (
    SELECT
        1 AS lgoffset
        , NULL AS lgdefval
        , ROW_NUMBER() OVER(PARTITION BY [Member] ORDER BY [Begin Date]) AS seq
        , [Member]
        , [Rank]
        , [Begin Date]
        , [End Date]
    FROM #table 
)
SELECT
    a.seq
    , a.[Member]
    , a.[Rank]
    , a.[Begin Date]
    , CASE
        WHEN a.[Rank] = 'B' AND a.[Begin Date] <= ISNULL(aLag.[End Date], a.lgdefval)
        THEN ISNULL(aLag.[End Date], a.lgdefval)
        ELSE a.[Begin Date]
      END AS bdate2
    , a.[End Date]
INTO #b
FROM a
LEFT OUTER JOIN a aLag
    ON a.seq = aLag.seq + a.lgoffset
    AND a.[Member] = aLag.[Member]
ORDER BY [Member], [Begin Date];


UPDATE #table
SET #table.bdate = CASE
                    WHEN #table.rnk = 'B' AND #table.bdate <= (SELECT #b.bdate2 FROM #b WHERE #b.bdate2 > #b.bdate and #table.mbr = #b.mbr)
                    THEN dateadd(d, 1,(SELECT bdate2 FROM #b WHERE #b.bdate2 > #b.bdate and #table.mbr = #b.mbr )) 
                    ELSE #table.bdate
                    END  

编辑PS:以下是我之前的回答,仅适用于 2012 年及以后的版本。

您可能想尝试以下 SELECT 语句以查看是否获得所需结果,然后转换为 UPDATE:

SELECT 
[Member]
, [Rank]
, CASE
    WHEN [Rank] = 'B' AND [Begin Date] <= LAG([End Date],1,'12/31/2030') OVER(PARTITION BY [Member] ORDER BY [Begin Date]) 
    THEN DATEADD(d,1,LAG([End Date],1,'12/31/2030')OVER(PARTITION BY [Member] ORDER BY [Begin Date]))
    ELSE [Begin Date]
  END AS [Begin Date]
, [End Date]
FROM #Table
ORDER BY [Member], [Begin Date]

编辑:所以为了更新开始日期列:

UPDATE #Table
SET [Begin Date] = (SELECT
                    CASE
                        WHEN [Rank] = 'B' AND [Begin Date] <= LAG([End Date],1,'12/31/2030') OVER(PARTITION BY [Member] ORDER BY [Begin Date]) 
                        THEN DATEADD(d,1,LAG([End Date],1,'12/31/2030')OVER(PARTITION BY [Member] ORDER BY [Begin Date]))
                        ELSE [Begin Date]
                      END AS [Begin Date]
                    FROM #Table)

编辑 2:由于没有意识到滞后函数需要 OVER 语句、更新的 select 语句和更新语句

,我的一些代码不正确

来源:Alternate of lead lag function in sql server 2008

http://blog.sqlauthority.com/2011/11/24/sql-server-solution-to-puzzle-simulate-lead-and-lag-without-using-sql-server-2012-analytic-function/