2016-11-20 53 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 Server 2008卡住了,所以lead()lag()是不可能的。

任何幫助非常感謝。

回答

1

這可能是用於SQL Server 2008的可能的(計算上昂貴的)溶液:

在第一步驟中,第一記錄被確定。在第二步中,查詢爲每個現有記錄確定最近的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