Sql-Server

SQL 規範是否需要 EXISTS () 中的 GROUP BY

  • March 24, 2017

Microsoft 目前允許這種語法。

SELECT *
FROM ( VALUES (1) ) AS g(x)
WHERE EXISTS (
 SELECT *
 FROM ( VALUES (1),(1) )
   AS t(x)
 WHERE g.x = t.x
 HAVING count(*) > 1
);

請注意,子句中沒有GROUP BYEXISTS是有效的 ANSI SQL。或者它只是暴露了一個實現細節。

作為參考,PostgreSQL 中不允許使用相同的語法。

錯誤:列“tx”必須出現在 GROUP BY 子句中或在聚合函式中使用

但是這種語法是允許的..

SELECT *
FROM ( VALUES (1) ) AS g(x)
WHERE EXISTS (
 SELECT 1  -- This changed from the first query
 FROM ( VALUES (1),(1) )
   AS t(x)
 WHERE g.x = t.x
 HAVING count(*) > 1
);

並且這種語法是允許的。

SELECT *
FROM ( VALUES (1) ) AS g(x)
WHERE EXISTS (
 SELECT *
 FROM ( VALUES (1),(1) )
   AS t(x)
 WHERE g.x = t.x
 GROUP BY t.x  -- This changed from the first query
 HAVING count(*) > 1
);

問題來自與@ErikE 在聊天中的對話

我在 SQL 2011 規範中找到了它…

如果<select list>“*”簡單地包含在<table subquery>立即包含在 an中的 a 中<exists predicate>,則 the<select list>等價於 a<value expression>是任意的<literal>

這證實了*在這種情況下不等同於任意文字,它實際上是 PostgreSQL 違反了規範。

請記住,這是一個明顯的問題

SELECT *
FROM ( VALUES (1),(2),(3) ) AS t(x)
HAVING count(*) > 1

兩個數據庫都拒絕。

PostgreSQL,

錯誤:列“tx”必須出現在 GROUP BY 子句中或在聚合函式中使用

SQL 伺服器,

列 ’tx’ 在選擇列表中無效,因為它既不包含在聚合函式中,也不包含在 GROUP BY 子句中。

為什麼這個錯誤在 PostgreSQL 中仍然存在

感謝 irc.freenode.net/#PostgreSQL 上的 RhodiumToad 幫助解決此問題。他還指出了解決這種情況的困難

20:33 < RhodiumToad> 的一個問題是,在 pg 中你可以做 exists(select func() from … 其中 func() 是一個可能返回 0 行的 SRF

SRF 是一個集合返回函式。

在 PostgreSQL 中,我們可以使用 SRF 來生成 1-10 的系列(generate_series在核心中)

SELECT * FROM generate_series(1,10); 

而且,我們也可以把它放在這裡。

SELECT generate_series(1,10);

其中兩個一起給了我們一個交叉連接(笛卡爾積)

SELECT generate_series(1,10), generate_series(1,2);

但是,如果其中任何一個返回 0 行,您將一無所獲。實際上與此相同

SELECT * FROM ( VALUES (1) ) AS t(x)
CROSS JOIN ( SELECT 1 LIMIT 0 ) AS g;

而且,這就是完全優化它的問題。您可以在返回 0 行的 EXIST 語句內的選擇列表中包含 SRF,並強制 EXISTS 評估為假。

引用自:https://dba.stackexchange.com/questions/168047