1

我真的不知道如何解决这个问题,需要一些帮助——不仅是解决方案,而且是如何解决的想法都会受到欢迎。

我有下表:

TABLE Data
( 
     RecordID
    ,DateAdd
    ,Status
)

示例日期如下:

11  2012-10-01 OK
11  2012-10-04 NO
11  2012-11-05 NO
22  2012-10-01 OK
33  2012-11-01 NO
33  2012-11-15 OK

此表具有以下示例数据:

TABLE Periods
(
    PeriodID
   ,PeriodName
   ,DateStart
   ,DateEnd
)

1 Octomer  2012-10-01 2012-10-31
2 November 2012-11-01 2012-11-30

我需要做的是填充一个新表:

TABLE DataPerPeriods
(
    PeriodID,
    RecordID,
    Status
)

这将存储 PeriodID 和 RecordID 的所有可能组合以及 period 的最新状态(如果可用)。如果给定期间的状态不可用,则为以前期间的状态。如果根本没有以前的状态 - 那么状态为 NULL。

例如,对于以下数据,我需要这样的东西:

1 11 NO //We have status "OK" and "NO", but "NO" is latest for the period
1 22 OK 
1 33 NULL//Because there are no records for this and previous periods
2 11 NO //We get the previos status as there are no records in this periods
2 22 OK //There are not records for this period, but record for last periods is available
2 33 NO //We have status "OK" and "NO", but "OK" is latest for the period

编辑:我已经在最后一个表中填充了期间 id 和记录 id,我需要更多关于状态更新的帮助。

4

3 回答 3

1

可能有更好的方法来做到这一点。但这是我所知道的最直接的途径,可以得到你正在寻找的东西,看起来非常规。对于较大的数据集,您可能必须更改方法:

SELECT p.PeriodID, td.RecordID, statusData.[Status] FROM Periods p
CROSS JOIN (SELECT DISTINCT RecordID FROM Data) td
OUTER APPLY (SELECT TOP 1 [Status], [DateAdd] 
         FROM Data 
         WHERE [DateAdd] <= p.DateEnd 
         AND [RecordID] = td.RecordID 
         ORDER BY [DateAdd] DESC) statusData
ORDER BY p.PeriodID, td.RecordID

CROSS JOIN 为您提供了 RecordIDs 和 DISTINCT Periods 的所有可能组合。

OUTER APPLY 选择每个周期结束之前的最新状态。

于 2012-11-02T14:35:55.520 回答
1

查看我对另一个问题的回答,了解如何获取第一个或最后一个状态:Aggregate SQL Function to grab only the first from each group

于 2012-11-02T14:23:52.280 回答
1

好的,这是一个想法。没有人喜欢光标,包括我在内,但有时它们确实会派上用场。

这个想法是这个游标循环遍历每个数据记录,提取 ID 作为标识符。在循环内,它会找到一条数据记录并获取满足您条件的连接计数。

如果@count = 0,则不满足条件,您不应插入该期间的记录。

如果@Count=1,则满足条件,因此插入该期间的记录。

如果这些条件需要经常更新,您可以查询作业并每分钟或每小时运行一次......你有什么。

希望这可以帮助。

DECLARE @ID int
DECLARE merge_cursor CURSOR FAST_FORWARD FOR 
select recordID
from data 
OPEN merge_cursor
FETCH NEXT FROM merge_cursor INTO @ID

WHILE @@FETCH_STATUS = 0
BEGIN

--get join if record is found in the periods
    declare @Count int
    select @Count= count(*) 
    from data a inner join periods b 
    on a.[dateadd] between b.datestart and b.dateend  
    where a.recordID = @ID 

    if @count>0

        --insert into DataPerPeriods(PeriodID, RecordID, Status)
        select b.periodid, a.recordid, a.status 
        from data a inner join periods b on a.[dateadd] between b.datestart and b.dateend --between beginning of  month and end of  month
        where a.recordid = @ID  
    else
        --insert into DataPerPeriods(PeriodID, RecordID, Status)
        select b.periodid, a.recordid, a.status 
        from data a inner join periods b on a.[dateadd] < b.dateend 
        where a.recordID = @ID --fix this area

FETCH NEXT FROM merge_cursor INTO @ID
END

CLOSE merge_cursor 
DEALLOCATE merge_cursor 
于 2012-11-02T14:51:01.787 回答