在 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 而不是EXISTSIN @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 5SELECT 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 会忽略选定的列?的主要内容,如果未能解决你的问题,请参考以下文章

计算 SQL 中选定 ID 的列总和

SQL左连接忽略第一个字母的列

DB2 SQL:如何将“WHERE EXISTS”表中的列添加到选择语句

Firefox 在使用 Tab 时会忽略选定元素上的轮廓和焦点样式

SQL 语句插入

可以 Go 的 Rows.Scan 忽略 SQL 查询中的字段