优化多行计数

时间:2012-12-05 18:25:36

标签: mysql join count

有两个表:questionanswer。在answer user_idquestion_idSELECT 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; 。我想计算每个选择的次数。

下面是一个有效的查询,但不是加入同一个表4次,更快的方法是加入答案表一次。

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

返回

{{1}}

3 个答案:

答案 0 :(得分: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中。

答案 1 :(得分:0)

如果您担心性能,可以考虑使用SELECT ... UNION SELECT样式。

虽然我同意@benjam你应该解析结果,看看优化器在说什么,因为你没有依赖查询。

答案 2 :(得分:0)

确保您在question.question_idanswer.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` ;

GROUP BY子句不需要和隐含ORDER BY子句。