2

我想我应该以某种方式知道这一点,尤其是在阅读了很多关于“条件必须进入 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)。

现在我只想获得那些具有 question_id 2 和 8 的任务(例如)所以如果一个任务没有这两个 question.ids,我不希望它出现在结果集中。在这种情况下,任务也可能有其他 question_id。尽管如果查询应该只返回那些恰好具有那些 2(或任何其他集合)的查询,那么看看查询的外观会很有趣。WHERE question.id = 2 很容易得到所有只有一个问题的任务,但是 WHERE 子句中的 AND 会导致结果为空。

4

5 回答 5

2

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

另一种解决方案是找到有问题 28 的任务,然后使用 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
于 2011-08-23T22:46:58.997 回答
0

即使不使用 and ... where question.id IN (2,8) 也可以做到这一点

于 2011-08-23T20:42:56.727 回答
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)
于 2011-08-23T20:43:29.263 回答
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)
于 2011-08-23T20:44:17.883 回答
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。糟糕的交易。

于 2011-08-23T20:46:16.380 回答