使用零计数的左连接和内连接对结果进行分组
Grouping results with left and inner join with zero counts
我有一个类似
的查询
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 子句中,我将丢失我的零结果(因为左连接 returns 一个空行)。
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`;
哪个returns
+--------------+-------+
| 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
添加另一个检查以防 participants
.appraisee_id
是 NULL
:
WHERE `campaign_questions`.`id` = 1
AND (`participants`.`appraisee_id` = 1
OR `participants`.`appraisee_id` IS NULL)
当你有 left join
并且你想过滤任何 table 但首先,你需要将条件放在 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`;
我还添加了 table 别名。它们使查询更易于编写和阅读。
关于这个问题的更新,我试着从不同的角度尝试这个查询。它似乎输出了我期望的结果,但是我不确定这是否是最有效的方法,因为我不得不使用子查询。
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`;
我有一个类似
的查询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 子句中,我将丢失我的零结果(因为左连接 returns 一个空行)。
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`;
哪个returns
+--------------+-------+
| 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
添加另一个检查以防 participants
.appraisee_id
是 NULL
:
WHERE `campaign_questions`.`id` = 1
AND (`participants`.`appraisee_id` = 1
OR `participants`.`appraisee_id` IS NULL)
当你有 left join
并且你想过滤任何 table 但首先,你需要将条件放在 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`;
我还添加了 table 别名。它们使查询更易于编写和阅读。
关于这个问题的更新,我试着从不同的角度尝试这个查询。它似乎输出了我期望的结果,但是我不确定这是否是最有效的方法,因为我不得不使用子查询。
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`;