2012-10-11 84 views
1

我知道總有一種更好的方式來做某件事,但我不知道該怎麼做?什麼是優化此查詢的最佳方法?我應該使用連接,單獨的查詢等。我知道這不是一個複雜的查詢..只是想擴大我的知識。SubSelect or Joins?有沒有更好的方式來編寫這個mysql查詢?

任何建議,將不勝感激!

SELECT 
    community_threads.id AS thread_id, 
    community_threads.title AS thread_title, 
    community_threads.date AS thread_date, 
    community_threads.author_id AS author_id, 
    `user`.display_name AS author_name, 
    `user`.organization AS author_organization, 
    (SELECT date FROM community_replies replies WHERE replies.thread_id = community_threads.id ORDER BY date DESC LIMIT 1) AS reply_date, 
    (SELECT count(id) FROM community_replies replies WHERE replies.thread_id = community_threads.id ORDER BY date DESC LIMIT 1) AS total_replies 
FROM 
    community_threads 
INNER JOIN `user` ON community_threads.author_id = `user`.id 
WHERE 
    category_id = '1' 
ORDER BY 
    reply_date DESC 
LIMIT 0, 5 

回答

1

這可以用JOIN針對子選擇它獲取每thread_id和骨料MAX(date)骨料COUNT()得到改善。除了對每行的子查詢進行評估之外,對於整個查詢,派生表只應計算一次,並與來自community_threads的其餘行進行連接。

SELECT 
    community_threads.id AS thread_id, 
    community_threads.title AS thread_title, 
    community_threads.date AS thread_date, 
    community_threads.author_id AS author_id, 
    `user`.display_name AS author_name, 
    `user`.organization AS author_organization, 
    /* From the joined subqueries */ 
    maxdate.date AS reply_date, 
    threadcount.num AS total_replies 
FROM 
    community_threads 
    INNER JOIN `user` ON community_threads.author_id = `user`.id 
    /* JOIN against subqueries to return MAX(date) (same as order by date DESC limit 1) and COUNT(*) from replies */ 
    /* number of replies per thread_id */ 
    INNER JOIN (
    SELECT thread_id, COUNT(*) AS num FROM replies GROUP BY thread_id 
) threadcount ON community_threads.id = threadcount.thread_id 
    /* Most recent date per thread_id */ 
    INNER JOIN (
    SELECT thread_id, MAX(date) AS date FROM replies GROUP BY thread_id 
) maxdate ON community_threads.id = maxdate.thread_id 
WHERE 
    category_id = '1' 
ORDER BY 
    reply_date DESC 
LIMIT 0, 5 

如果你把LIMIT 0, 5reply_date子查詢中你可能會得到更好的性能。那隻會拉取子查詢中最近的5個,並且INNER JOIN將會丟棄全部來自community_threads的不匹配。

/* I *think* this will work...*/ 
SELECT 
    community_threads.id AS thread_id, 
    community_threads.title AS thread_title, 
    community_threads.date AS thread_date, 
    community_threads.author_id AS author_id, 
    `user`.display_name AS author_name, 
    `user`.organization AS author_organization, 
    /* From the joined subqueries */ 
    maxdate.date AS reply_date, 
    threadcount.num AS total_replies 
FROM 
    community_threads 
    INNER JOIN `user` ON community_threads.author_id = `user`.id 
    INNER JOIN (
    SELECT thread_id, COUNT(*) AS num FROM replies GROUP BY thread_id 
) threadcount ON community_threads.id = threadcount.thread_id 
    /* LIMIT in this subquery */ 
    INNER JOIN (
    SELECT thread_id, MAX(date) AS date FROM replies GROUP BY thread_id ORDER BY date DESC LIMIT 0, 5 
) maxdate ON community_threads.id = maxdate.thread_id 
WHERE 
    category_id = '1' 
ORDER BY 
    reply_date DESC 
+0

有趣,謝謝..從來沒有想過使用MIN/MAX之前。一旦我獲得聲望,我會投票。 – cire

0

盡我所知,這看起來像是一個羣體的好機會。

SELECT 
    community_threads.id AS thread_id, 
    community_threads.title AS thread_title, 
    community_threads.date AS thread_date, 
    community_threads.author_id AS author_id, 
    `user`.display_name AS author_name, 
    `user`.organization AS author_organization, 
    MAX(replies.date) AS reply_date, 
    COUNT(replies.id) AS total_replies 
FROM community_threads 
INNER JOIN `user` ON community_threads.author_id = `user`.id 
INNER JOIN community_replies AS replies ON replies.thread_id = community_threads.id 
WHERE category_id = 1 
GROUP BY thread_id, thread_title, thread_date, author_id, author_name, author_organization) 
ORDER BY reply_date DESC 
LIMIT 0, 5 

希望這會有所幫助。

相關問題