2012-12-05 35 views
1

有兩個表格:questionanswer。在answer我持有user_idquestion_id。我想統計每個選擇被選擇的次數。優化多行計數

下面是一個正在工作的查詢,但不是連接同一個表4次,而是一種更快的方式,即只加入一次答案表。

SELECT question.question_id, 
    question.correct_choice, 
    COUNT(DISTINCT a.user_id) as num_of_a, 
    COUNT(DISTINCT b.user_id) as num_of_b, 
    COUNT(DISTINCT c.user_id) as num_of_c, 
    COUNT(DISTINCT d.user_id) as num_of_d 
FROM answer a, 
    answer b, 
    answer c, 
    answer d, 
    question 
WHERE a.question_id = question.question_id 
    AND b.question_id = question.question_id 
    AND c.question_id = question.question_id 
    AND d.question_id = question.question_id 
    AND a.choice = 'A' 
    AND b.choice = 'B' 
    AND c.choice = 'C' 
    AND d.choice = 'D' 
GROUP BY question.question_id 
ORDER BY question.question_id asc; 

回報

273, D, 5, 2, 8, 39 
274, C, 2, 14, 50, 2 
277, C, 3, 5, 41, 17 
278, C, 16, 9, 34, 9 
279, C, 8, 30, 24, 12 
280, B, 17, 21, 20, 3 
284, C, 2, 3, 19, 1 
286, A, 16, 3, 2, 2 
287, D, 1, 2, 1, 18 
289, B, 3, 18, 2, 2 
290, D, 6, 9, 8, 6 
+0

你可以提供有關表格結構的信息嗎? –

+0

現在的方式有什麼問題?有了適當的索引,這應該是一個相當快的查詢。 – Benjam

回答

1

該解決方案不僅單個連接......另外,我轉換您的默許加入到明確,並殺進了您的GROUP BY

SELECT 
    q.question_id, 
    q.correct_choice, 
    COUNT(DISTINCT CASE WHEN a.choice = 'A' THEN a.user_id END) as num_of_a, 
    COUNT(DISTINCT CASE WHEN a.choice = 'B' THEN a.user_id END) as num_of_b, 
    COUNT(DISTINCT CASE WHEN a.choice = 'C' THEN a.user_id END) as num_of_c, 
    COUNT(DISTINCT CASE WHEN a.choice = 'D' THEN a.user_id END) as num_of_d 
FROM 
    answer a 
    JOIN question q ON a.question_id = q.question_id 
GROUP BY q.question_id, q.correct_choice 
ORDER BY q.question_id asc; 

這工作,因爲當CASE語句不計算爲true它將返回NULL,這將不包含在用戶ID的COUNT DISTINCT中。

+0

完美謝謝!只需在num_of_d後刪除逗號即可。 –

+0

@BahadırİsmailAydın啊謝謝...我錯過了 - 修復! –

0

如果你關心性能,您可以考慮使用SELECT ... UNION SELECT風格。

雖然我會同意@benjam,你應該解釋結果,看看優化器說什麼,因爲你沒有依賴查詢。

0

請確保您有question.question_id指標,並在answer.question_idanswer.choiceanswer.user_id和您的查詢應該是一樣快,因爲任何其他不爲每個選項加入的答案。然後使用以下查詢:

SELECT `question`.`question_id`, 
    `question`.`correct_choice`, 
    COUNT(DISTINCT `a`.`user_id`) as `num_of_a`, 
    COUNT(DISTINCT `b`.`user_id`) as `num_of_b`, 
    COUNT(DISTINCT `c`.`user_id`) as `num_of_c`, 
    COUNT(DISTINCT `d`.`user_id`) as `num_of_d` 
FROM `question` 
    LEFT JOIN `answer` AS `a` 
     USING(`a`.`question_id` = `question`.`question_id` 
      AND `a`.`choice` = 'A'), 
    LEFT JOIN `answer` AS `b` 
     USING(`b`.`question_id` = `question`.`question_id` 
      AND `b`.`choice` = 'B'), 
    LEFT JOIN `answer` AS `c` 
     USING(`c`.`question_id` = `question`.`question_id` 
      AND `c`.`choice` = 'C'), 
    LEFT JOIN `answer` AS `d` 
     USING(`d`.`question_id` = `question`.`question_id` 
      AND `d`.`choice` = 'D') 
GROUP BY `question`.`question_id` ; 

ORDER BY子句不是必需的,它隱含在GROUP BY子句中。