【问题标题】:Grouping results with left and inner join with zero counts使用零计数的左连接和内连接对结果进行分组
【发布时间】:2015-01-27 17:13:34
【问题描述】:

我有一个类似的查询

SELECT 
    `campaign_question_options`.`text`, 
    COUNT(`campaign_submission_answers`.`answer`) as `count`
    FROM `campaign_questions`
    INNER JOIN `campaign_question_options` ON `campaign_question_options`.`campaign_question_id` = `campaign_questions`.`id`
    LEFT JOIN `campaign_submission_answers` ON `campaign_submission_answers`.`answer` = `campaign_question_options`.`text` AND `campaign_submission_answers`.`campaign_question_id` = 1
    LEFT JOIN `campaign_submissions` ON `campaign_submissions`.`id` = `campaign_submission_answers`.`campaign_submission_id`
    LEFT JOIN `participants` ON `participants`.`id` = `campaign_submissions`.`participant_id`
WHERE 
    `campaign_questions`.`id` = 1
GROUP BY `campaign_submission_answers`.`answer` 
ORDER BY `campaign_question_options`.`index`;

这给了我一个类似的结果集

+--------------+-------+
|     text     | count |
+--------------+-------+
| 1 (positive) |   114 |
| 2            |    48 |
| 3 (neutral)  |    34 |
| 4            |     6 |
| 5 (negative) |     0 |
+--------------+-------+

所以问题是我需要在participants.appraisee_id 列上进一步过滤结果。但是,如果我将其添加到 where 子句中,我将丢失零结果(因为左连接返回空行)。

SELECT 
    `campaign_question_options`.`text`, 
    COUNT(`campaign_submission_answers`.`answer`) as `count`
FROM `campaign_questions`
INNER JOIN `campaign_question_options` ON `campaign_question_options`.`campaign_question_id` = `campaign_questions`.`id`
LEFT JOIN `campaign_submission_answers` ON `campaign_submission_answers`.`answer` = `campaign_question_options`.`text` AND `campaign_submission_answers`.`campaign_question_id` = 1
LEFT JOIN `campaign_submissions` ON `campaign_submissions`.`id` = `campaign_submission_answers`.`campaign_submission_id`
LEFT JOIN `participants` ON `participants`.`id` = `campaign_submissions`.`participant_id`
WHERE 
    `campaign_questions`.`id` = 1 AND `participants`.`appraisee_id` = 1
GROUP BY `campaign_submission_answers`.`answer` 
ORDER BY `campaign_question_options`.`index`;

返回

+--------------+-------+
|     text     | count |
+--------------+-------+
| 1 (positive) |    16 |
| 2            |     1 |
+--------------+-------+

其实我想要的时候

+--------------+-------+
|     text     | count |
+--------------+-------+
| 1 (positive) |    16 |
| 2            |     1 |
| 3 (neutral)  |     0 |
| 4            |     0 |
| 5 (negative) |     0 |
+--------------+-------+

谁能帮我改进这个查询?

谢谢

更新

我已经创建了该结构的数据库转储,如果有任何人希望继续帮助我,这可能会很有用。 https://gist.github.com/simonbowen/a8316fe91c78b8464402

【问题讨论】:

  • 很高兴您向我们展示了您的尝试,但如果是我,我会从正确的 DDL(和/或 sqlfiddle)开始,并获得所需的结果
  • @Strawberry 你是对的,但是它不允许我加载数据(8000 个字符限制)。这是结构sqlfiddle.com/#!2/0f7e5
  • 我们不需要看到整个事情。足以具有代表性。
  • @Strawberry 好的,我已经提供了结构的小提琴,并且还在评论更新中提供了转储。我在问题的末尾概述了我的预期结果。

标签: mysql sql join count group-by


【解决方案1】:

当您有left joins 并且想要过滤除第一个以外的任何表时,您需要将条件放在on 子句中:

SELECT cqo.`text`, 
       COUNT(csa.`answer`) as `count`
FROM `campaign_questions` cq INNER JOIN
     `campaign_question_options` cqo 
     ON cqo.`campaign_question_id` = cq.`id` LEFT JOIN
     `campaign_submission_answers` csa
     ON csa.`answer` = cqo.`text` AND csa.`campaign_question_id` = 1 LEFT JOIN
     `campaign_submissions` cs
     ON cs.`id` = csa.`campaign_submission_id LEFT JOIN
     `participants` p
     ON p.`id` = cs.`participant_id` AND
        p. appraisee_id = XXX
WHERE cq.`id` = 1
GROUP BY csa.`answer` 
ORDER BY cqo.`index`;

我还添加了表别名。它们使查询更易于编写和阅读。

【讨论】:

  • 我不得不稍微修改一下语句以使别名正确,因为它没有在 text 列的选择上引用正确的别名。然而,一旦我解决了这个问题,我最终得到了我的问题中概述的第一个结果集。
  • 为了详细说明更改,我不得不将co.text更改为cqo.text
【解决方案2】:

关于这个问题的更新,我尝试从不同的角度尝试这个查询。它似乎输出了我期望的结果,但是我不确定这是否是最有效的方法,因为我不得不使用子查询。

SELECT `campaign_question_options`.`text`, COUNT(`csa`.`answer`) FROM `campaign_questions`
INNER JOIN `campaign_question_options`  ON `campaign_question_options`.`campaign_question_id` = `campaign_questions`.`id`
LEFT JOIN (
   SELECT `campaign_submission_answers`.* FROM `campaign_submission_answers`
   INNER JOIN `campaign_submissions` ON `campaign_submissions`.`id` = `campaign_submission_answers`.`campaign_submission_id`
   INNER JOIN `participants` ON `participants`.`id` = `campaign_submissions`.`participant_id`
   INNER JOIN `campaign_questions` ON `campaign_questions`.`id` = `campaign_submission_answers`.`campaign_question_id`
   INNER JOIN `campaign_question_options` ON `campaign_question_options`.`text` = `campaign_submission_answers`.`answer` 
   WHERE `campaign_submissions`.`campaign_id` = 1 AND `participants`.`appraisee_id` = 1 AND `campaign_submission_answers`.`campaign_question_id` = 1
   GROUP BY `campaign_submission_answers`.`id`
) as `csa` ON `csa`.`answer` = `campaign_question_options`.`text`
WHERE `campaign_questions`.`id` = 1
GROUP BY `campaign_question_options`.`text`;

【讨论】:

    【解决方案3】:

    添加另一个检查以防participants.appraisee_idNULL

    WHERE `campaign_questions`.`id` = 1 
      AND (`participants`.`appraisee_id` = 1 
       OR `participants`.`appraisee_id` IS NULL)
    

    【讨论】:

    • 这很接近,但它并没有给我所有选项的零计数 1(正)16 2 1 5(负)0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 2013-04-12
    • 2022-06-17
    相关资源
    最近更新 更多