[英]Join: three tables and a or condition
我想我应该以某种方式知道这一点,尤其是在阅读了许多有关“条件必须进入ON子句,而不是WHERE子句”的问题和答案之后。 但是,我仍然迷路。
我有三个表,我通常通过LEFT(OUTER)联接将它们联接。 联接的表如下所示(非常标准):
task_id task_questions_taskId taskQuestions_questionId question_id 1 1 5 5 1 1 8 8 2 2 8 8
SELECT `t`.`id` AS `task_id` ,
`task_questions`.`taskId` AS `task_questions_taskId` ,
`task_questions`.`questionId` AS `task_questions_questionId` ,
questions.id AS question_id
FROM `task` `t`
LEFT OUTER JOIN `task_questions` `task_questions`
ON ( `task_questions`.`taskId` = `t`.`id` )
LEFT OUTER JOIN `question` `questions`
ON ( `task_questions`.`questionId` = `questions`.`id` )
这是获取所有记录的标准查询。 (它取自Yii;我实际上想通过Active Record做到这一点,但是甚至无法正确使用普通SQL)。
现在,我只想获取那些具有question_id 2和8的任务(例如),因此,如果一个任务没有两个question_id,那么我就不希望它出现在结果集中。 在这种情况下,任务也可以具有其他question_id。 尽管如果查询仅返回恰好具有这2个(或任何其他集合)的查询,将会看到查询的外观,这很有趣。 使用WHEREquestion.id = 2可以很容易地获得所有具有一个问题的任务,但是WHERE子句中的AND导致结果为空。
WHERE子句一次只能将条件应用于一行。 但是,不同ID的问题出现在不同的行上。 如何解决呢? 使用self-join将两行连接为一行。
这是一个例子:
SELECT t.`id` AS `task_id`, ...
FROM `task` AS t
INNER JOIN `task_questions` AS tq2 ON ( tq2.`taskId` = t.`id` )
INNER JOIN `questions` AS q2 ON ( tq2.`questionId` = q2.`id` )
INNER JOIN `task_questions` AS tq8 ON ( tq8.`taskId` = t.`id` )
INNER JOIN `questions` AS q8 ON ( tq8.`questionId` = q8.`id` )
WHERE q2.`id` = 2 AND q8.`id` = 8
另一个解决方案是找到具有问题2 或 8的任务,然后使用GROUP BY和HAVING按正好具有两个问题的组进行筛选。
SELECT t.`id` AS `task_id`, ...
FROM `task` AS t
INNER JOIN `task_questions` AS tq ON ( tq.`taskId` = t.`id` )
INNER JOIN `questions` AS q ON ( tq.`questionId` = q.`id` )
WHERE tq.`questionId` IN (2, 8)
GROUP BY t.`id`
HAVING COUNT(DISTINCT q.`id`) = 2
您甚至可以在不使用和的情况下执行此操作... where question.id IN(2,8)
使用IN
:
SELECT `t`.`id` AS `task_id` ,
`task_questions`.`taskId` AS `task_questions_taskId` ,
`task_questions`.`questionId` AS `task_questions_questionId` ,
questions.id AS question_id
FROM `task` `t`
LEFT OUTER JOIN `task_questions` `task_questions`
ON ( `task_questions`.`taskId` = `t`.`id`)
LEFT OUTER JOIN `question` `questions`
ON ( `task_questions`.`questionId` = `questions`.`id` )
WHERE `task_questions`.`questionId` IN (2, 8)
这应该做
SELECT `t`.`id` AS `task_id` ,
`task_questions`.`taskId` AS `task_questions_taskId` ,
`task_questions`.`questionId` AS `task_questions_questionId` ,
questions.id AS question_id
FROM `task` `t`
LEFT OUTER JOIN `task_questions` `task_questions`
ON ( `task_questions`.`taskId` = `t`.`id` )
LEFT OUTER JOIN `question` `questions`
ON ( `task_questions`.`questionId` = `questions`.`id` )
WHERE questions.id in (2,8)
您不是在寻找AND,而是在寻找OR,或者是IN:
WHERE `questions`.`id` IN (2,8) -- grab everything in the parens.
要么
WHERE `questions`.`id` = 2 OR -- grab each item individually
`questions`.`id` = 8
如果使用AND
,则ID必须同时为8和2。 不好
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.