2016-11-20 6 views
3

私はこの形式でレコードを持つテーブルを持っている:このプロセスのカーソルの代わりに?

SPECIAL_ID | OTHER_ID | NAME | TIMESTAMP 

私はこれをベースにして新しいテーブルを作成しますが、唯一の少なくとも25分間隔前のものからあるレコードを取得する必要があります。間隔は一貫していません。レコード1から始めると、レコード1のタイムスタンプから少なくとも25分後の次のレコードを取得する必要があります。これは新しいテーブルのレコード2になります。そして、抽出された前のレコードの25分後の次のレコード。だから、ここの情報の一例である:

AAA | 1 | WHATEVER2 | 2016-11-20 00:00:00 
BCD | 2 | WHATEVER00 | 2016-11-20 00:02:00 
AAA | 3 | WHATEVER01 | 2016-11-20 00:09:00 
AAA | 4 | WHATEVER55 | 2016-11-20 00:20:00 
XYZ | 5 | WHATEVER | 2016-11-20 00:24:00 
AAA | 6 | WHATEVER11 | 2016-11-20 00:45:00 
QRS | 7 | WHATEVER | 2016-11-20 00:46:00 
QRS | 8 | WHATEVER12 | 2016-11-20 00:59:00 
AAA | 9 | WHATEVER12 | 2016-11-20 01:02:00 
AAA |10 | WHATEVER12 | 2016-11-20 01:17:00 

そして、私は何をしようとしています:

AAA | 1 | WHATEVER2 | 2016-11-20 00:00:00 
AAA | 6 | WHATEVER11 | 2016-11-20 00:45:00 
AAA |10 | WHATEVER12 | 2016-11-20 01:17:00 

私は、カーソルを使用して管理し、レコードの小さなセットでそれをテストしました。それは働いた....しかし、私は百万のこのように分析する必要があります。カーソルはただのトラブルを求めているようです。

これを行うより良い方法はありますか?

私はSQLサーバー2008に固執していますので、lead()lag()は質問になりません。

大変助かりました。これは、SQL Server 2008の可能性(計算コスト)ソリューションであることができ

答えて

1

:最初のステップでは

、最初のレコードが決定されます。 2番目のステップでは、既存のレコードごとに最も近い25分のレコードがクエリーによって決定されます。 続いて(ステップ3)、データレコードは、OTHER_IDが最も小さいレコードに縮小されます。もちろん、これはOTHER_IDが一意でフィールドが時刻と同期している場合にのみ機能します。 何百万ものレコードについては、クエリで使用されるフィールドにインデックスを付け、検索を制限する必要があります。

-- test script 

SET dateformat ymd 

;WITH testdata AS (
    SELECT 'AAA'  AS SPECIAL_ID, 
     1   AS OTHER_ID, 
     'WHATEVER2' AS NAME , 
     CONVERT(DATETIME, '2016-11-20 00:00:00') AS [TIMESTAMP] 
    UNION SELECT 'BCD' , 2 , 'WHATEVER00' , CONVERT(DATETIME, '2016-11-20 00:02:00') 
    UNION SELECT 'AAA' , 3 , 'WHATEVER01' , CONVERT(DATETIME, '2016-11-20 00:02:01') 
    UNION SELECT 'AAA' , 4 , 'WHATEVER55' , CONVERT(DATETIME, '2016-11-20 00:20:00') 
    UNION SELECT 'XYZ' , 5 , 'WHATEVER' , CONVERT(DATETIME, '2016-11-20 00:24:00') 
    UNION SELECT 'AAA' , 6 , 'WHATEVER11' , CONVERT(DATETIME, '2016-11-20 00:45:00') 
    UNION SELECT 'QRS' , 7 , 'WHATEVER' , CONVERT(DATETIME, '2016-11-20 00:46:00') 
    UNION SELECT 'QRS' , 8 , 'WHATEVER12' , CONVERT(DATETIME, '2016-11-20 00:59:00') 
    UNION SELECT 'AAA' , 9 , 'WHATEVER12' , CONVERT(DATETIME, '2016-11-20 01:02:00') 
    UNION SELECT 'AAA' ,10 , 'WHATEVER12' , CONVERT(DATETIME, '2016-11-20 01:17:00') 
    UNION SELECT 'QRS' ,11 , 'WHATEVER13' , CONVERT(DATETIME, '2016-11-20 01:30:00') 
), firstRecord AS (
    SELECT SPECIAL_ID, MIN(OTHER_ID) AS OTHER_ID 
    FROM testdata 
    GROUP BY SPECIAL_ID 
), nextRecord1 AS (
    SELECT I1.SPECIAL_ID, I1.OTHER_ID AS OTHER_ID, MIN(I2.OTHER_ID) AS next_OTHER_ID 
    FROM testdata I1 
     INNER JOIN testdata I2 
       ON I1.SPECIAL_ID = I2.SPECIAL_ID 
       AND I1.OTHER_ID < I2.OTHER_ID 
       AND I2.[TIMESTAMP] >= DATEADD(minute, 25, I1.[TIMESTAMP]) 
    GROUP BY I1.SPECIAL_ID, I1.OTHER_ID 
), nextRecord2 AS (
    SELECT SPECIAL_ID, MIN(OTHER_ID) AS OTHER_ID, next_OTHER_ID 
    FROM nextRecord1 
    GROUP BY SPECIAL_ID, next_OTHER_ID 
) 
SELECT T2.* 
    FROM firstRecord T1 
     INNER JOIN testdata T2 
       ON T1.OTHER_ID = T2.OTHER_ID 
UNION 
SELECT T2.* 
    FROM nextRecord2 T1 
     INNER JOIN testdata T2 
       ON T1.next_OTHER_ID = T2.OTHER_ID 
関連する問題