2012-06-25 196 views
0

我有一張表,其中包含鏈接到另一個表的優先級記錄。添加結束日期以記錄下一個記錄的開始日期

FK - Priority - PriorityUpdateDateTime

我想要做的就是添加結束日期,此表,但只是作爲一個臨時表。

所以我需要的是FK - Priority - StartDate - EndDate

在哪裏結束日期是下一個PriorityUpdateDateTime

FK - Priority - PriorityUpdateDateTime

123 - 4 - 2011-02-25

123 - 2 - 2011-02-30

123 - 3 - 2011-03-10

變爲

FK - Priority - StartDate - EndDate

123 - 4 - 2011-02-25 - 2011-02-30

123 - 2 - 2011-02-30 - 2011-03-10

123 - 3 - 2011-03-10 - NULL

感謝您的幫助

回答

1

好吧,你可以使用子選擇這樣的:

-- nasty sub select, lets see if we can do better 
SELECT T1.[FK], 
     T1.[Priority], 
     T1.[PriorityUpdateDateTime] AS 'StartDate', 
     (
      SELECT MAX(T2.[PriorityUpdateDateTime]) AS MP 
      FROM @test AS T2 
      WHERE T2.[FK] = T1.[FK] 
       AND T2.[Priority] < T1.[Priority] 
     ) AS 'EndDate' 
FROM @test AS T1 

這裏是我暫時的腳本來創建測試表和數據

DECLARE @test AS TABLE 
(
    [FK] INT NOT NULL, 
    [Priority] INT NOT NULL, 
    [PriorityUpdateDateTime] DATETIME NOT NULL 
) 

INSERT INTO @test VALUES(123, 4, '20110225') 
INSERT INTO @test VALUES(123, 3, '20110228') -- there are only 28 days in Feb in 2011 (not 30) 
INSERT INTO @test VALUES(123, 2, '20110310') 

-- nasty sub select, lets see if we can do better 
SELECT T1.[FK], 
     T1.[Priority], 
     T1.[PriorityUpdateDateTime] AS 'StartDate', 
     (
      SELECT MAX(T2.[PriorityUpdateDateTime]) AS MP 
      FROM @test AS T2 
      WHERE T2.[FK] = T1.[FK] 
       AND T2.[Priority] < T1.[Priority] 
     ) 
FROM @test AS T1 
+0

感謝凱恩,工作就像一個魅力 – Matt

+0

希望有人能做到這一點沒有一個子查詢/子選擇,因爲我不相信他們是太有效率,並會造成與大型數據集的問題。 – Kane

+0

我不確定我做錯了什麼,但是執行你的腳本並沒有提出正確的答案。在評論中不能做CrLf(取而代之),但這是我在運行代碼時得到的結果... FK Priority StartDate | ----------- ----------- ----------------------- ---- ------------------- | 123 4 2011-02-25 00:00:00。000 2011-03-10 00:00:00.000 | 123 3 2011-02-28 00:00:00.000 2011-03-10 00:00:00.000 | 123 2 2011-03-10 00:00:00.000 NULL | –

0

@馬特@Kane

凱恩做精除了他爲不平等選擇了錯誤的列。我只是做了幾個更正。如果有人能夠想出一種更快的方法,而不是可能會使相關的子查詢和CROSS APPLY方法受到關注的「Quirky Update」,我會感到驚訝。

下面是構建更多測試數據的代碼,而不是您可以爲實現性能測試而搖擺不定。

--===== Conditionallly drop the test table to make reruns in SSMS easier 
    IF OBJECT_ID('tempdb..#Test','U') IS NOT NULL 
     DROP TABLE #Test 
; 
--===== Create and populate the test table on-the-fly 
    -- using a "Pseudo Cursor" which is many times 
    -- faster than a WHILE loop. 
SELECT TOP 100000 
     FK = ABS(CHECKSUM(NEWID()))%100+100, -- 100 thru 199 
     Priority = ABS(CHECKSUM(NEWID()))%100+1, -- 1 thru 100 
     PriorityUpdateDateTime = DATEADD(dd, 
            ABS(CHECKSUM(NEWID()))%DATEDIFF(dd,'2000','2010') 
           ,'2000') --20000101 thru 20091231 
    INTO #Test 
    FROM sys.all_columns ac1 --has more than 4000 rows even on a new system 
    CROSS JOIN sys.all_columns ac2 
; 
--===== Create a clustered index to improve performance by about 10 times in this case 
CREATE INDEX IX_#Test ON #Test (FK,PriorityUpdateDateTime) 
; 

以下是凱恩代碼的兩種不同的表達方式。細節在代碼中。兩者在相同的時間內返回相同的結果。

--===== Kane's correlated subquery works just fine here once we 
    -- flip it around and use a different column name in the 
    -- inequality part. 
SELECT t1.FK, 
     t1.Priority, 
     StartDate = t1.PriorityUpdateDateTime, 
     EndDate = 
      ( 
      SELECT MIN(t2.PriorityUpdateDateTime) 
       FROM #Test t2 
       WHERE t2.FK = t1.FK 
       AND t2.PriorityUpdateDateTime > t1.PriorityUpdateDateTime 
      ) 
    FROM #Test t1 
    ORDER BY t1.FK, t1.PriorityUpdateDateTime, t1.Priority 
; 
--===== Or, you could use a CROSS APPLY and get the same thing because 
    -- a CROSS APPLY isn't much more than a correlated sub-query. 
SELECT t1.FK, 
     t1.Priority, 
     StartDate = t1.PriorityUpdateDateTime, 
     d.EndDate 
    FROM #Test t1 
    CROSS APPLY 
     ( 
     SELECT MIN(t2.PriorityUpdateDateTime) 
      FROM #Test t2 
      WHERE t2.FK = t1.FK 
      AND t2.PriorityUpdateDateTime > t1.PriorityUpdateDateTime 
     ) d (EndDate) 
    ORDER BY t1.FK, t1.PriorityUpdateDateTime, t1.Priority 
; 
相關問題