如何使用需要从同一个表中的其他几行中排序的数据更新行?

时间:2014-09-18 11:48:32

标签: sql sql-server sql-server-2005

我正在尝试使用同一个表的另一行中包含的数据更新(SQL Server 2005)表的行。问题基本上可以归结为:

我有一个现有的表,其中包含IDSTART_DATEEND_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和不要,请大声说出来。

2 个答案:

答案 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
相关问题