【问题标题】:SQL correlated subquery of the same table同一张表的SQL关联子查询
【发布时间】:2015-10-31 20:33:06
【问题描述】:

我有桌子:

Person(SSN, name, address)
Car(license, year, model)
Accident(license, accident-date, driver, damage-amount)
Owns(SSN, license)

问题问:

查找涉及不止一次事故的所有汽车的牌照号码(请勿返回重复项)。

答案之一是:

SELECT DISTINCT A1.license 
FROM Accident A1 
WHERE A1.license IN (SELECT A2.license 
                     FROM Accident A2 
                     WHERE A1.accident-date <> A2.accident-date)

它从不检查相关子查询中的 A1.license = A2.license。所以据我了解,子查询检查 A1 中的元组是否与 A2 中的元组具有不同的事故日期,即使这两个元组具有不同的许可证。那么这不应该是错误的吗?

编辑:假设汽车一天不能发生超过一次事故。

【问题讨论】:

  • 这个“答案”是完全错误的,如果Accident 中有多个日期,它会返回所有行。正如你已经说过的,缺少AND A1.license = A2.license
  • 这适用于哪个 RDBMS?请添加标签以指定您使用的是mysqlpostgresqlsql-serveroracle 还是db2 - 或其他完全不同的东西。
  • 问题没有具体说明,但是由于我的班是学mysql的,所以我已经标记了mysql。
  • 答案是不正确的,除非你假设一辆车不能在同一天发生两次事故。
  • 对不起,我应该这么说的。假设一辆汽车一天不能发生一次以上的事故。

标签: mysql sql subquery correlated-subquery


【解决方案1】:

实际上IN 操作员正在检查许可证是否相等。让我们做一个测试。假设Accidents 表包含行:

License  AccidentDate
L1       20151001
L1       20151020
L2       20151025

为外部查询的每一行评估相关子查询。想象一个在行上循环的游标。

对于row1 A.LicenceL1。内部子查询只检查与20151001 不同的日期,它会找到row2row3(L1, L3)。所以A.LicenceL1 在内部子查询的结果集中,它将在最终结果中返回。第二排也是如此。但是row3 将不包括在内,因为除20151025 之外的日期中没有L2。所以查询是正确的。

【讨论】:

  • 为什么不会从子查询返回第 3 行?在子查询中,我们从不检查 A1.license = A2.license。那么,子查询会将row3的日期和row1的日期进行比较,日期不同,所以它会返回,不是吗?
  • 否,子查询将日期与外部查询当前行的日期进行比较。 Where 子句将消除 IN 谓词评估为 false 的所有行。现在想象在外部查询中,您处于第 3 行的位置。 L2 20151025. 内部子查询呢?它搜索除日期 20151025 之外的日期以外的 ros,并找到 20151001 和 20151020,但两者都是 L1,因此当您处于位置 row3 时,您会得到 L2 IN(L1)。所以谓词是假的,第 3 行被过滤掉了。
  • 用文字来表达:给我这样的事故行,其中许可证号可以在一组许可证号中找到,日期不是我的崩溃日期。如果我发现自己和其他日期在一组,这意味着这辆车多次发生碰撞。
  • 好的,让我试着理解这一点。 IN 子句的作用是检查 A1.license = A2.license。当我们向下迭代到 A2.row3 时,我们想将日期与 A1 中的行进行比较。但由于 L1 IN L2 为假,我们不检查许可证为 L1 的行。
  • 哦。对于外部查询中的每个元组,我们执行内部查询。我的印象是子查询首先完全执行,然后外部查询检查返回的结果,但这是针对不相关的子查询。谢谢!我现在明白了。
猜你喜欢
  • 2016-12-11
  • 2022-07-06
  • 2017-06-11
  • 2020-03-08
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多