2012-12-05 33 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子句中。