2011-07-26 75 views
0

我有三個表 - tblpollquestions,tblpollanswers和tblpollresponses。mysql限制連接 - 是否有更高效的方法來執行此操作?

我想選擇一個用戶還沒有回答的隨機問題,並帶有相應的答案。

下面的SQL返回正是我所需要的,但我擔心它需要三個SELECT來做到這一點。肯定有更有效的方法嗎?

SELECT 
    poll.id, 
    poll.question, 
    a.answer 
FROM tblpollquestions poll 
INNER JOIN tblpollanswers a ON a.question_id = poll.id 
INNER JOIN (
    SELECT id FROM tblpollquestions WHERE id NOT IN(
     SELECT question_id FROM tblpollresponses WHERE user_id = 1 
    ) ORDER BY RAND() LIMIT 1 
) as t ON t.id = poll.id 
+0

對我來說很好。它如何執行?解釋計劃說什麼? – Randy

回答

0

這可以由通過切換NOT IN(SELECT...)好一點到LEFT JOIN

SELECT 
    poll.id, 
    poll.question, 
    a.answer 
FROM 
    tblpollquestions poll 
INNER JOIN 
    tblpollanswers a 
ON 
    a.question_id = poll.id 
INNER JOIN (
    SELECT 
     q.id 
    FROM 
     tblpollquestions AS q 
    LEFT JOIN 
     tblpollresponses AS r 
    ON 
     q.id = r.question_id 
     AND r.user_id = 1 
    WHERE 
     r.question_id IS NULL 
    ORDER BY RAND() LIMIT 1 
) as t ON t.id = poll.id 

ORDER BY RAND()也可能會很慢,如果有在tblpollquestions表中的許多行。查看Bill Karwin的這篇演示文稿(幻燈片142及以後),瞭解關於選擇隨機行的一些其他想法。

http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back

+0

MySQL非常好地優化了'ORDER BY RAND()LIMIT 1' - 它實際上相當快。如果你正在比較我的查詢,LEFT JOIN與IS NULL和NOT EXISTS在MySQL中應該有相同的速度。 (看看解釋 - 他們應該是相同的。)但我認爲在一個地方做會比加入更快。編輯:也許不是:http://jan.kneschke.de/projects/mysql/order-by-rand/ - 你將需要解釋這兩個版本,並根據這個決定。 – Ariel

+0

我還沒有聽說過ORDER BY RAND()優化。你能提供任何關於它的信息的鏈接嗎?就你的'NOT EXISTS'子查詢而言 - 你使用了依賴子查詢 - 我認爲MySQL 5.4或更新版本可以處理這個問題,但是舊版本對於外部查詢中的每一行運行這樣的子查詢是一個臭名昭着的事情。 – Mchl

+0

請參閱:http://dev.mysql.com/doc/refman/5.0/en/limit-optimization.html MySQL實際上並沒有通過rand()對整個表進行排序 - 它只獲取一行並停止。 – Ariel

0

是,似乎沒什麼問題,但我會稍微改變:

SELECT 
    poll.id, 
    poll.question, 
    a.answer 
FROM tblpollquestions poll 
INNER JOIN tblpollanswers a ON a.question_id = poll.id 
WHERE poll.id = (
    SELECT id FROM tblpollquestions WHERE NOT EXISTS (
     SELECT * FROM tblpollresponses WHERE user_id = 1 AND question_id = tblpollquestions.id) 
    ORDER BY RAND() LIMIT 1) 

書面這種方式應該做的使用索引,而不是檢查每一個連接條件更好的工作tblpollanswers

確保你有一個UNIQUE指數(或主鍵)上tblpollresponses(user_id, question_id)(按順序)。如果您需要將其用於其他查詢,則可以按相反順序添加附加UNIQUE索引。

編輯:其實把它放在哪裏可能不是那麼好http://jan.kneschke.de/projects/mysql/order-by-rand/你需要對explain進行查詢和比較。

0

使用左加入這樣的:

SELECT ques.id, ques.question, ans.answer FROM tblpollquestions ques 
INNER JOIN tblpollanswers ans ON(ans.question_id = ques.id) 
left join tblpollresponses res on(res.question_id=ques.id and user_id = 1) 
where res.question_id is null ORDER BY RAND() LIMIT 1; 

我改變了你的表的別名,以做出更好的感覺。

相關問題