【问题标题】:Is this SQL query guaranteed to join correctly?此 SQL 查询是否保证正确加入?
【发布时间】:2013-02-09 00:22:03
【问题描述】:

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

question_recordsenrollmentsquestions 都有一个外键

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_recordenrollment_id 为 11,question_id 为 500。如果此查询不是逐个记录搜索条件,它将匹配在 500 的 question_id 上并返回记录。这不是我想要的行为。我只想要 both enrollment_id question_id 与给定记录匹配的记录。我得到的答案涵盖了这种情况。

【问题讨论】:

  • 为了让其他人回答您的问题,您必须非常清楚地解释您期望从查询中返回什么。
  • 对于特定部分,不,查询将永远不会返回“enrollment_id 为 11,question_id 为 500”的行。对于此查询,(enrollment_id, question_id) 的唯一组合是 (10,500)(10,600)(20,500)(20,600)
  • @ypercube Hurgh,很好的收获。我把INBETWEEN 弄糊涂了。
  • @millimoose 也许 OP 也有同样的困惑。否则11 的问题没有多大意义。
  • @ypercube 这就是我所需要的。只是想确保我没有遗漏一些微妙的东西。

标签: sql inner-join


【解决方案1】:

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

  1. 您从question_recordsenrollmentsquestions 中获取所有行。
  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))

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

【讨论】:

  • 这太棒了。花时间了解 INNER JOIN 相当于什么是我需要的步骤。谢谢。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 2013-06-11
    • 2023-03-17
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多