1

別のテーブルにリンクする優先度の記録を含むテーブルがあります。

FK - Priority - PriorityUpdateDateTime

私がやろうとしているのは、このテーブルに終了日を追加することですが、一時テーブルとしてのみです。

だから私が必要なのはFK - Priority - StartDate - EndDate

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

ご協力いただきありがとうございます

4

2 に答える 2

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
于 2012-06-25T01:40:33.043 に答える
1

@マット@ケイン

ケインは、不等式のために間違った列を選んだことを除いて、うまくいきました。いくつか修正しました。誰かが、相関するサブクエリとCROSS APPLYメソッドからドアを吹き飛ばす「風変わりな更新」以外のより高速なメソッドを思い付くことができれば、私は驚きます。

これは、パフォーマンステストの目的でスティックを振ることができるよりも多くのテストデータを構築するためのコードです。

--===== 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のコードの2つの異なる表現です。詳細はコードにあります。どちらもほぼ同じ時間で同じ結果を返します。

--===== 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
;
于 2012-06-25T03:21:31.127 に答える