在 SQL 中使用 EXISTS 会忽略选定的列?
Posted
技术标签:
【中文标题】在 SQL 中使用 EXISTS 会忽略选定的列?【英文标题】:Using EXISTS in SQL ignores selected columns? 【发布时间】:2014-04-03 05:04:36 【问题描述】:SELECT st.state_id,
st.state_name,
st.country_id
FROM state_table st
WHERE EXISTS (SELECT 0 / 0
FROM country c
WHERE st.country_id = c.country_id
AND c.country_name = 'India')
此查询产生与st.country_id = c.country_id
匹配的预期输出。然而,在此查询中,内部子查询中的0 / 0
预计将替换为c.country_id
。
等效的 IN()
查询如下所示。
SELECT st.state_id,
st.state_name,
st.country_id
FROM state_table st
WHERE country_id IN(SELECT c.country_id
FROM country c
WHERE c.country_name = 'India')
似乎EXISTS()
子查询内的select
子句中的列列表被忽略了。这是真的吗?
【问题讨论】:
是的。重要的是子选择是否找到任何行。 我建议使用JOIN
而不是EXISTS
或IN
。
@user2864740 - 使用 SELECT 1,这使得选择更简单,只需要构建一行/列即可建立 TRUE,甚至更好的用户 JOIN,正如 Barmar 建议的那样 - 它的速度更快。
@Barmar:mysql 的最新版本正确处理 IN
样式的半连接。无论如何,在这种情况下,子查询在大多数情况下可能只返回一行。
@PreetSangha 哦,好的。这将是我对 EXISTS 的新方式。
【参考方案1】:
似乎
EXISTS()
子查询内的select
子句中的列列表被忽略了。这是真的吗?
是的!重要的是它返回了多少行。
(实际上,如果某些 DBMS 至少评估字段列表,我不会感到惊讶,即使值本身被丢弃。所以0 / 0
可能不可移植。)
附录:我刚刚使用 sqlfiddle.com 进行了测试,似乎 MySQL 将 0 / 0
视为 NULL
而不是错误,所以这并不意味着;但即使在像 Oracle 这样通常确实将 0 / 0
视为错误的 DMBS 上,谓词 EXISTS (SELECT 0 / 0 ...)
也是成功的。那么,也许它是可移植的? (当然,我只测试了少数 DBMS —— MySQL、PostgreSQL、Oracle 和 SQL Server 各一个版本——所以我不能保证。)
【讨论】:
@Phil:我很确定它会。至少在某些 DBMS 中确实如此。为什么你认为它不会? 我在 Oracle 上花了很多年 + 直觉 :) @Phil:使用 sqlfiddle.com,我刚刚在 MySQL 5.5.23 上尝试了SELECT 1 FROM (SELECT 1) t WHERE EXISTS (SELECT NULL);
,在 Oracle 11gR2 上尝试了 SELECT 1 FROM dual WHERE EXISTS (SELECT NULL FROM dual);
,在 PostgreSQL 9.3.1 和 MS SQL Server 上尝试了 SELECT 1 WHERE EXISTS (SELECT NULL);
2012. 在所有情况下,它都成功返回了包含1
的单行。我猜你的直觉是错误的。 (不要因为有它而感到难过——对黑暗角落的直觉通常是错误的,因为我们通常的经验是避免它们——但下一次,一定要测试一下!)
很好证明。我在这个过程中得到了纠正并学到了一些东西:D
@Phil: MySQL: EXISTS - NOT EXISTS【参考方案2】:
似乎 EXISTS() 子查询中的 select 子句中的列列表被忽略了。这是真的吗?
是的,是的。
根据EXISTS
- NOT EXISTS
上的文档
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
传统上,EXISTS 子查询以SELECT *
开头,但它可以以SELECT 5
或SELECT column1
或任何东西。 MySQL 忽略SELECT list
在这样的子查询中,所以没有区别。对于前面的示例,如果 t2 包含任何行,即使行包含 只有 NULL 值,
EXISTS
条件为 TRUE。这是 实际上是一个不太可能的例子,因为[NOT] EXISTS
子查询几乎 总是包含相关性。
下面列出了对其他 DBMS 的一些解释:
-
Oracle: Exists and Not Exists with SubQueries
T-SQL Exists
PostgreSQL: Exists
【讨论】:
以上是关于在 SQL 中使用 EXISTS 会忽略选定的列?的主要内容,如果未能解决你的问题,请参考以下文章
DB2 SQL:如何将“WHERE EXISTS”表中的列添加到选择语句