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