【问题标题】:Mysql unknown column in subquery works子查询中的Mysql未知列有效
【发布时间】:2018-11-28 06:28:23
【问题描述】:

共有三个表 - mapping_hospital_proceduremaster_hospitalmaster_procedure

master_hospital 包含一个 id 列来标识每家医院。

master_procedure 还包含一个 id 列,用于相同目的,即识别每个过程。

mapping_hospital_procedure 用于将医院映射到医疗程序,除其他列外,还包含 hid(医院 ID)和 pid(程序 ID)列。现在,如果我运行这个查询:

SELECT hid FROM master_procedure

它没有像您期望的那样工作,因为master_procedure 中没有hid 列。但是如果我把这个查询放在一个子查询中,它工作得很好。比如像这样——

SELECT hid FROM mapping_hospital_procedure WHERE pid = (SELECT hid FROM master_procedure)

但它不应该工作,因为在master_procedure 中没有名为hid 的列。它应该给出与前一个查询相同的未知列错误。谁能解释这是为什么或如何工作的?

谢谢。

【问题讨论】:

标签: mysql sql subquery


【解决方案1】:

范围问题。您的子查询可以访问主查询的列。

由于在子查询表中找不到 hid,它会跳出并在主查询中查找它 - 在 mapping_hospital_procedure 表中找到它。

SELECT hid FROM mapping_hospital_procedure
WHERE pid = (SELECT hid FROM master_procedure)

一样
SELECT mhp.hid FROM mapping_hospital_procedure mhp
WHERE mhp.pid = (SELECT mhp.hid FROM master_procedure mp)

现在学到的教训:始终限定您的列!

编辑:“这至少应该是一个逻辑错误,输出不正确,对吧?

是的,这个查询没有多大意义。

如果 master_procedure 表根本不包含任何行,mhp.pid = (SELECT mhp.hid FROM master_procedure mp) 将为 false。根本不返回任何行。

如果 master_procedure 表包含 2 行或更多行,则应引发“子查询返回超过 1 行”异常。 (因为这是一个= 比较。使用IN 来避免这个问题。)

如果 master_procedure 表正好包含 1 行,如果 mhp.pid 不为空,mhp.pid = (SELECT mhp.hid FROM master_procedure mp) 条件的计算结果为 true,并且该行从 mapping_hospital_procedure 返回。如果 mhp.pid 为 null,则不返回该行。


你真正想做的可能是:

SELECT mhp.hid FROM mapping_hospital_procedure mhp
WHERE mhp.pid IN (SELECT mp.id FROM master_procedure mp)

【讨论】:

  • 因此,在这里的子查询中,如何从 master_procedure 访问 mhp.hid,因为它的值不存在于该表中。这至少应该是一个给出不正确输出的逻辑错误,对吧?
【解决方案2】:

通过该查询,您实际上是在进行自然连接。 https://www.w3resource.com/sql/joins/natural-join.php

数据库解析器足够智能,可以将您的查询转换为连接。 您的查询:

SELECT hid FROM mapping_hospital_procedure 
WHERE pid = (SELECT hid FROM master_procedure)

基本相同:

SELECT hid FROM mapping_hospital_procedure 
NATURAL JOIN master_procedure 
WHERE pid = hid

【讨论】:

  • 我认为这不是一个好的答案。首先,引擎的任何优化都是检查语法之后完成的,而不是之前。其次,自然连接需要两个表中具有相同名称的列,这里不存在。 dba 网站的答案似乎更准确。
猜你喜欢
  • 2013-10-20
  • 1970-01-01
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多