2012-10-22 97 views
3

的分組通過序列我有一個表,其中包含以下幾列和數據:SQL查詢幫助 - 位數

id  dtime  instance  data  dtype 

1  2012-10-22  10000  d  1 
2  2012-10-22  10000  d  1 
.. 
7  2012-10-22  10004  d  1 
.. 
15 2012-10-22  10000  @  1 
16 2012-10-22  10004  d  1 
17 2012-10-22  10000  d  1 

我想組序列「D的數據列,用‘@’在序列的末尾。

這可能是通過實例列進行分組完成的,實例列是一個單獨的數據流,但是流內可以有多個序列。

如果在同一個實例中沒有數據列,例如在該實例的最後一個數據後3秒,並且在該間隔內沒有找到'@',我也想結束一個序列。

我已經設法使用遊標和while循環來完成這項工作,對於具有1000行的表格,這些循環可以很好地工作,但是這個查詢最終會用在更多的行上,而這兩種方法大約需要一分鐘時間只有3-5000行的數據集。

閱讀本網站和其他人,似乎基於集合的邏輯可能是要走的路,但我可以想象沒有辦法做我所需要的,沒有每行上的某種循環來比較每一行其他建立'序列'。

如果任何人都可以幫忙,或者指出我的方向,那將是不勝感激。 :)

我會非常喜歡的數據是按以下格式輸出:

DATACOUNT例如lastdata DTIME

20  10000 @  2012-10-22 

19  10000 d  2012-10-22 

22  10004 @  2012-10-22 

20  10022 @  2012-10-22 

凡(DATACOUNT)是行數的計數的'序列'(這是導致'@'或3秒延遲的數據),(實例)是來自原始表的實例ID,(lastdata)是序列中的最後一個數據值,(dtime)是日期時間最後一個數據值的值。

+0

什麼是您的問題中發佈的數據所需的輸出? –

+0

對不起,我忘了添加這個問題,我現在編輯它,並添加所需的輸出到底部。 – gabbiccino

+0

如果從原始數據構建結果集花費的時間過長,您可以使用例如「一個觸發器 –

回答

1

讓我告訴你如何做最後的'@'。時間差異遵循類似的想法。關鍵的想法是在當前行之後獲得下一個'@'。爲此,你需要一個相關的子查詢。之後,您可以通過以下方式進行分組:

select groupid, count(*) as NumInSeq, max(dtime) as LastDateTime 
from (select t.*, 
      (select min(t2.id) from t t2 where t2.id > t.id and t2.data = '@' 
      ) as groupid 
     from t 
    ) t 
group by groupid 

處理時間序列有點複雜。這是這樣的:

select groupid, count(*) as NumInSeq, max(dtime) as LastDateTime, 
     (case when sum(case when data = '@' then 1 else 0 end) > 0 then '@' else 'd' end) as FinalData 
from (select t.*, 
      (select min(t2.id) 
       from t t2 
       where t2.id > t.id and 
        (t2.data = '@' or UNIX_TIMESTAMP(t2.dtime) - UNIX_TIMESTAMP(t.dtime) < 3 
      ) as groupid 
     from t 
    ) t 
group by groupid 
+0

謝謝戈登,查詢在返回任何東西之前超時,但是我會在較小的數據集上嘗試一下,找出導致減速的原因。 – gabbiccino

+0

不幸的是,相關的子查詢不能很好地優化。在其他數據庫中,替代解決方案將使用窗口函數,但這些在MySQL中不可用。如果您有(id,data)索引並解除時間限制,這可能會有所幫助。 –

+0

在更好地排序的數據集上重試查詢,並且它在while循環方法執行時間的大約四分之一時間內運行。仍然有一些奇怪的結果,其中1個數據行被計爲17,這是我無法理解的,但我會繼續努力。謝謝你的幫助。 :) – gabbiccino