2012-11-02 103 views
1

我真的沒有想法如何解決這個問題,需要一些幫助 - 不僅解決方案,但如何接近的想法將受到歡迎。T-SQL需要複雜連接幫助

我有如下表:

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的所有可能組合,以及期限的最新狀態(如果可用)。如果狀態在給定期間不可用,則爲以前期間的狀態。如果根本沒有以前的狀態 - 則表示狀態爲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在最後一個表,我需要狀態更新更多的幫助。

回答

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和不同的時期的每一個可能的組合。

OUTER APPLY在每個期間結束之前選擇最新狀態。

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