2014-09-25 62 views
0

以下是我的MySQL查詢,查找每個帳戶的連續日期之間的差異,然後使用結果準備頻率計數表。這個查詢當然很慢,但在此之前我做的是正確的事情?如果可以的話請幫忙。嵌入的也是一個小數據樣本。 欣賞你的時間。 OZooHAMySQL查詢很慢 - 在組級別的連續日期的差異

 ID DATE 
    403 2008-06-01 
    403 2012-06-01 
    403 2011-06-01 
    403 2010-06-01 
    403 2009-06-01 
    15028 2011-07-01 
    15028 2010-07-01 
    15028 2009-07-01 
    15028 2008-07-01 

SELECT 
    month_diff, 
    count(*) 
FROM 
(SELECT t1.id, 
     t1.date, 
     MIN(t2.date) AS lag_date, 
     TIMESTAMPDIFF(MONTH, t1.date, MIN(t2.date)) AS month_diff 
FROM tbl_name T1 
     INNER JOIN tbl_name T2 
      ON t1.id = t2.id 
      AND t2.date > t1.date 
GROUP BY t1.id, t1.date 
ORDER BY t1.id, t1.date 
) 
GROUP BY month_diff 
ORDER BY month_diff 

回答

1

有可能的,物化線視圖走的大部分時間。確保您有合適的索引可用來提高聯接操作的性能;覆蓋索引ON tbl_name (id, date)對於此查詢可能是最佳的。

可用一個合適的指數(如上)有可能與查詢像這樣,以獲得更好的性能:

SELECT d.month_diff 
    , COUNT(*) 
    FROM (SELECT IF(@prev_id = t.id 
        , TIMESTAMPDIFF(MONTH, t.date, @prev_date) 
        , NULL 
       ) AS month_diff 
       , @prev_date := t.date 
       , @prev_id := t.id 
      FROM tbl_name t 
      CROSS 
      JOIN (SELECT @prev_date := NULL, @prev_id := NULL) i 
      GROUP BY t.id DESC, t.date DESC 
     ) d 
WHERE d.month_diff IS NOT NULL 
GROUP BY d.month_diff 

注意,MySQL用戶自定義變量的使用不能保證。但是,我們確實觀察到以特定方式寫入的查詢的一致行爲。 (MySQL的未來版本可能會改變我們觀察到的行爲。)


編輯:我修改了上面的查詢,以GROUP BY t.id, t.date更換ORDER BY t.id, t.date ......目前尚不清楚,從示例數據(id,date)是否保證獨一無二。 (如果我們確實有這種保證,那麼我們不需要GROUP BY,我們可以使用ORDER BY。否則,我們需要GROUP BY以獲得原始查詢返回的相同結果。)

+0

爲什麼你會困擾初始化您的@爲空?您可以取消交叉連接。 – Arth 2014-09-25 19:39:58

+1

@Arth:因爲否則我們不能保證第一次在語句中引用它們時,會在'@ prev_id'和'@ prev_date'中指定什麼值。是的,交叉連接到內聯視圖可能會被廢棄,並且可以用單獨的'SET @prev_date = NULL'和'SET @prev_id = NULL'語句替換。 (用戶定義的變量會保留在會話中,我們不知道當語句開始執行時在它們中存儲了什麼值;如果這些變量沒有初始化,我們可以證明得到了「錯誤」的結果(我的首選是包含在這個聲明中udvs的初始化) – spencer7593 2014-09-25 19:44:40

+0

有道理,謝謝你,我沒有在聲明之外思考! – Arth 2014-09-25 20:10:18