2010-01-18 123 views
0

我每天運行一個查詢來編譯統計信息 - 但它看起來效率很低。這是查詢:Mysql子選擇查詢優化

SELECT a.id, tstamp, label_id, (SELECT author_id FROM b WHERE b.tid = a.id ORDER BY b.tstamp DESC LIMIT 1) AS author_id 
FROM a, b 
WHERE (status = '2' OR status = '3') 
AND category != 6 
AND a.id = b.tid 
AND (b.type = 'C' OR b.type = 'R') 
AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end} 
ORDER BY b.tstamp DESC 
LIMIT 500 

此查詢似乎運行速度非常慢。爲廢話命名道歉 - 我被要求不透露實際的表名稱。

有一個子選擇的原因是因爲外部select從表a得到一行,它從表b得到一行。但是也需要知道表b中的最新author_id,所以我運行一個子選擇來返回那個。我不想在php循環內運行另一個選擇 - 因爲這也是低效的。

它工作正常 - 我只需要找到一個更快得到這個數據集的方法。

+0

@Matt:你應該嘗試提供的答案,upvote有幫助,並接受解決你的問題。如果他們都沒有,請考慮編輯您的問題以提供更多信息。 – 2010-01-23 08:08:50

回答

2

如果b.tstampb.tid是獨一無二的,採取OMG小馬的解決方案。

否則,您可以嘗試此解決方案。它將整個結果按b.tstamp DESC排序,並按照author_id添加排名。外部選擇僅獲取rank = 1的行,這是author_id中最大的tstamp

SELECT id, tstamp, label_id, author_id 
    FROM (SELECT id, 
       tstamp, 
       label_id, 
       author_id, 
       CASE 
       WHEN @author_id != author_id THEN @row_num := 1 
       ELSE @row_num := @row_num + 1 
       END AS rank, 
       @author_id := b.author_id 
      FROM a, 
       b, 
       (SELECT @row_num := 0, @author_id := NULL) y 
      WHERE a.id = b.tid 
      AND (status = '2' OR status = '3') 
      AND category != 6 
      AND (b.type = 'C' OR b.type = 'R') 
      AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end} 
      ORDER BY b.author_id, b.tstamp DESC 
) x 
WHERE x.rank = 1 
LIMIT 500 

我還沒有嘗試過,所以請評論,如果它不起作用。

2

嘗試:

SELECT a.id, 
     b.tstamp, 
     label_id, 
     y.author_id 
    FROM TABLE_A a 
    JOIN TABLE_B b ON b.tid = a.id 
    JOIN (SELECT b.tid, 
       MAX(b.tstamp) 'm_tstamp' 
      FROM TABLE_B b 
     GROUP BY b.tid) x ON x.tid = a.id 
    JOIN (SELECT b.tid, 
       b.author_id, 
       b.tstamp 
      FROM TABLE_B b 
     GROUP BY b.tid) y ON y.tid = a.id 
         AND y.tstamp = x.m_tstamp 
    WHERE status IN ('2', '3') 
    AND b.type IN ('C', 'R') 
    AND category != 6 
    AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end} 
ORDER BY b.tstamp DESC 
    LIMIT 500 
+0

@Peter Lang:謝謝!糾正。 – 2010-01-18 16:58:16