加入:三个表和一个或条件

时间:2011-08-23 20:39:11

标签: mysql sql join sql-match-all

我想我应该知道这一点,特别是在阅读了很多关于“条件必须进入ON子句而不是WHERE子句”的问题和答案之后。但是,我还是输了。

我有三个表,我通常使用LEFT(OUTER)连接加入它们。连接表看起来像这样(retty标准):


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)。

现在我想得到那些有问题2和8(例如)的任务 因此,如果任务没有这两个question.ids,我不希望它在结果集中。 在这种情况下,任务也可以有其他question_ids。虽然如果它只返回那些具有那些2(或任何其他集合)的那些查询将会如何看起来会很有趣。 使用WHERE question.id = 2,很容易得到所有有一个问题的任务, 但是WHERE子句中的AND会导致空结果。

5 个答案:

答案 0 :(得分:1)

WHERE子句一次只能将条件应用于一行。但是你对不同id的问题出现在不同的行上。怎么解决这个?使用自联接将两行连接到一行。

以下是一个例子:

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 OR 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

答案 1 :(得分:0)

即使没有使用和,你也可以这样做 ...其中question.id IN(2,8)

答案 2 :(得分:0)

使用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)

答案 3 :(得分:0)

这应该这样做

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)

答案 4 :(得分:0)

你不是在寻找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。糟糕的交易。