2014-07-24 40 views
-3

我有一個查詢,它使用兩個連接,返回我的列表格式如下:在列表中選擇值的首次亮相(DISTINCT/GROUP BY)

unique_id | non_unique_id | timestamp 

的完整列表大(千行),查詢的結果是隻有幾十行,如查詢有其中timestamp> =「一些戳過去」

所以,現在,我有名單如下:

89 | 286 | 1406219705 
87 | 286 | 1406219518 
79 | 922 | 1406216949 
78 | 228 | 1406216871 
77 | 126 | 1406216748 
76 | 939 | 1406216722 
74 | 126 | 1406216352 
64 | 939 | 1406212540 
63 | 126 | 1406212522 
49 | 228 | 1406205715 
48 | 228 | 1406204851 
37 | 228 | 1406196435 
32 | 228 | 1406190209 
23 | 126 | 1406182577 <- 'limiting timestamp' 
18 | 871 | 1406181991 
10 | 922 | 1406178816 
9 | 764 | 1406178778 
7 | 609 | 1406178699 
5 | 126 | 1406177398 
4 | 871 | 1406177379 <- 'some timestamp in the past' 

現在,我只需要選擇'限制時間戳'和列表末尾('過去的某個時間戳')之間的行。我可以在原始查詢的WHERE條件中指定'限制時間戳',但問題是:我需要得到的集合沒有non_unique_id的記錄,這些記錄已經出現在上方的列表中,限制時間戳'。這是查詢的結果如何應該是這樣的:

     <- 'limiting timestamp' 
18 | 871 | 1406181991 

9 | 764 | 1406178778 
7 | 609 | 1406178699 

         <- 'some timestamp in the past' 

那麼結果將返回3行,它們都具有未出現在上述結果non_unique_id。但是,如果'non_unique_id'已經出現在'限制時間戳''過去''某個時間戳之間的列表中,那麼只應保留第一次出現。注意:最後一部分的條件是可選的,因爲從最終列表中提取重複數據非常容易。

到目前爲止,我只能夠拿出做列表之間的連接> =>「限制時間戳」「一些在過去的時間戳」的解決方案。這樣我會查看底部列表中是否有任何頂部列表出現。但是,可以假設查詢是複雜的,並且生成結果所需的時間不應該再次運行一次,而是需要稍微不同的條件。

+1

已爲您發佈回覆。但是我認爲你對JOIN解決方案的假設值得爭議:即使是EXISTS解決方案也是一個隱式遊標。我只是說不要認爲JOIN會變慢;用你的數據進行測試,看看會發生什麼。無論如何,祝你好運。 – VBlades

+1

那麼,哪個RDBMS? – Strawberry

回答

1

你可以試試這個如果SQL Server 2008+(sqlfiddle:http://sqlfiddle.com/#!3/0bc33/3):

WITH cteOrdered 
AS 
(
    SELECT ROW_NUMBER() OVER (PARTITION BY t1.Non_Unique_ID ORDER BY t1.Timestamp) AS RID, 
       t1.* 
    FROM  Table1 t1 LEFT JOIN 
       (SELECT Non_Unique_ID 
       FROM Table1 
       WHERE Timestamp < 1406177379 OR 
         Timestamp > 1406182577) t2 
       ON t1.Non_Unique_ID = t2.Non_Unique_ID 
    WHERE  t2.Non_Unique_ID IS NULL AND 
       t1.Timestamp > 1406177379 AND 
       t1.Timestamp < 1406182577 
) 

SELECT Unique_ID, 
      Non_Unique_ID, 
      Timestamp 
FROM  cteOrdered 
WHERE  RID = 1; 

我已經添加了另一行插入數據

(18, 871, 1406181990), 

查看查詢是否產生你想要的。你說如果在搜索範圍內有重複的non_unique_id,那麼只應該保留「第一」事件。我認爲這是與最早的時間戳?如果相反,你可以把這個信號

SELECT ROW_NUMBER() OVER (PARTITION BY t1.Non_Unique_ID ORDER BY t1.Timestamp) AS RID, 

改變

SELECT ROW_NUMBER() OVER (PARTITION BY t1.Non_Unique_ID ORDER BY t1.Timestamp DESC) AS RID, 

,這將翻轉,以保留重複項最新的時間戳。

1

試試這個:

SELECT * 
FROM my_table AS t1 
WHERE timestamp < @limiting_timestamp 
    AND timestamp > @some_timestamp_in_the_past 
    AND NOT EXISTS(SELECT 1 
       FROM my_table AS t2 
       WHERE timestamp > @limiting_timestamp 
       AND t1.non_unique_id = t2.non_unique_id) 

,將讓你的時間戳之間記錄的限制時間戳後不會發生。請注意,如果您想要的記錄等於過濾時間戳記,則可以使用between關鍵字而不是<和>。

爲了消除您可以使用另一個子查詢:

AND t1.timestamp = (SELECT MAX(timestamp) 
       FROM my_table AS t2 
       WHERE timestamp < @limiting_timestamp 
        AND timestamp > @some_timestamp_in_the_past 
       GROUP BY unique_id)