SQL 規範是否需要 EXISTS () 中的 GROUP BY
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 BY
,EXISTS
是有效的 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 評估為假。