我正在尝试使用同一个表的另一行中包含的数据更新(SQL Server 2005)表的行。问题基本上可以归结为:
我有一个现有的表,其中包含ID
,START_DATE
,END_DATE
和其他一些值(与此问题无关)的列。该表填充了每行ID
的多行,但具有不同的日期间隔。 START_DATE
是客户端显式设置的值,而END_DATE
是来自其系统的默认值。例如:
ID START_DATE END_DATE
===================================
1 2001-01-01 2099-12-31
1 2003-01-01 2099-12-31
1 2003-03-21 2099-12-31
2 2002-11-04 2099-12-31
2 2005-08-01 2099-12-31
. ... ...
. ... ...
该表包含大量数据,现在应将此数据导出到外部系统。唯一的问题是外部系统无法处理重叠的日期间隔。因此,我的目标是实现以下目标:
ID START_DATE END_DATE
===================================
1 2001-01-01 2002-12-31
1 2003-01-01 2003-03-20
1 2003-03-21 2099-12-31
2 2002-11-04 2005-07-31
2 2005-08-01 2099-12-31
. ... ...
. ... ...
我已经查看了其他类似的问题,但尚未找到我正在寻找的内容。
是否可以为此创建查询?
BTW:这是我在这里的第一个问题,所以如果我没有关注DO和不要,请大声说出来。
答案 0 :(得分:1)
您可以使用CTE并在以下Startdate - 1中更新它以获取ID'
Declare @a Table(ID int, START_DATE DateTime, END_DATE datetime)
insert into @a Select 1,'20010101','20991231'
insert into @a Select 1,'20030101','20991231'
insert into @a Select 1,'20030321','20991231'
insert into @a Select 2,'20021104','20991231'
insert into @a Select 2,'20050801','20991231'
;With CTE as
(
Select *, Row_Number() Over (Partition by ID order by Start_date) as RN
from @A
)
Update CTE SET END_DATE=ISNULL((Select START_DATE-1 from CTE ci where ci.ID=CTE.ID and ci.RN=CTE.RN+1),END_DATE)
Select * from @A
另一种适用于旧版SQLServer的方法是
Update aTable set END_DATE=ISNULL(
(Select Min(START_DATE)-1 from aTable ai where ai.ID=aTable.ID and ai.START_DATE>aTable.START_DATE)
,END_DATE)
答案 1 :(得分:0)
以下查询将执行所需的更新。我把DatePeriod作为表的名称。
UPDATE [DatePeriod] SET [DatePeriod].END_DATE=DpNew.NewEND_DATE
FROM [DatePeriod] Dp
INNER JOIN (
SELECT DP1.Id,DP1.START_DATE,DATEADD(day, -1, DP2.START_DATE) NewEND_DATE
FROM
(SELECT ROW_NUMBER()OVER(ORDER BY ID,START_DATE ) AS SNo,* FROM [DatePeriod] ) DP1
INNER JOIN
(SELECT ROW_NUMBER()OVER(ORDER BY ID,START_DATE ) AS SNo,* FROM [DatePeriod] ) DP2
ON DP1.ID=DP2.ID AND DP1.SNo=(DP2.SNO-1)
) DpNew ON DpNew.Id=Dp.Id and DpNew.START_DATE=DP.START_DATE