1

这是一个非常基本的问题,但出于某种原因,我无法让自己放心。我有一个 sql 查询,我想确保它按预期运行。

question_recordsenrollments两者都有一个外键questions

SELECT `question_records`.* FROM `question_records` 
  INNER JOIN `enrollments` ON `enrollments`.`id` = `question_records`.`enrollment_id` 
  INNER JOIN `questions` ON `questions`.`id` = `question_records`.`question_id` 
  WHERE (enrollments.id IN (10,20) 
         AND questions.id IN (500,600) 
         AND question_records.id not in (3000,4000))

我要确保的是,我不会得到一个问题记录,例如,enrollment_id 为 11,question_id 为 500。换句话说,这个内部连接是否逐个记录地处理这个 where 子句?更重要的是,它总是这样对待它吗?(我可以想出一个测试示例,但要确保我没有遗漏任何案例。

编辑:为清楚起见的附加叙述:

question_record数据库中可能存在 aenrollment_id为 11 和 aquestion_id为 500。如果此查询不是逐条记录搜索条件,它将匹配question_id500 并返回记录。这不是我想要的行为。我只想要给定记录匹配记录。我得到的答案涵盖了这种情况。enrollment_id question_id

4

2 回答 2

0

评估此查询的心智模型是:

  1. question_records您从、enrollments和中获取所有行questions
  2. 您创建这三个行集的笛卡尔积。(首先将所有内容与所有内容匹配。)
  3. 根据条件是否为真INNER JOIN过滤笛卡尔积的行。ON
  4. 然后根据最终WHERE条件对其进行过滤。
  5. 选择所需的列以形成最终结果。

(显然,数据库会将其优化为完全不同的东西。)

因此,如果一行符合INNER JOIN..ON条件,但不符合条件,WHERE则不会出现在最终结果中。它必须匹配所有条件。

当您知道您INNER JOIN的等效于以下时,这可能更容易理解:

SELECT qr.* FROM question_records qr
                 enrollments      e
                 questions        q
  WHERE e.id = qr.enrollment_id
    AND q.id = qr.question_id
    -- your original WHERE condition
    AND enrollments.id IN (10,20) 
    AND questions.id IN (500,600) 
    AND question_records.id not in (3000,4000))

(这种形式更符合我概述的心智模型。)

于 2013-02-09T01:27:54.963 回答
0

如果您的问题确实是 SQL 优化器是否会将 WHERE 子句中的条件推送到 JOIN 中并在执行连接之前对每个表进行过滤作为中间结果,那么答案是没有这样的保证,但在简单的情况下,例如这是任何体面的优化器的一半。

于 2013-02-09T01:36:51.567 回答