マイクロソフトでは現在、この構文を許可しています。
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
);
EXISTS
句にGROUP BY
がないことに注意してください。これは有効なANSI SQLです。それとも単に実装の詳細を公開するだけなのでしょうか。
参考までに、これと同じ構文はPostgreSQLでは許可されていません。
エラー:列 "t.x"は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>
に含まれる<exists predicate>
に単純に含まれている場合、<select list>
は<value expression>
と同等です。任意の<literal>
。
これは、このコンテキストでの*
が任意のリテラルと同等ではないことを確認しますそれは実際にPostgreSQLが仕様に違反していることを示しています。
これは別の問題であることを覚えておいてください
SELECT *
FROM ( VALUES (1),(2),(3) ) AS t(x)
HAVING count(*) > 1
どちらのデータベースが拒否するか。
PostgreSQL、
エラー:列 "t.x"はGROUP BY句に出現するか、集計関数で使用する必要があります
SQLサーバー、
列 't.x'は、集約関数にもGROUP BY句にも含まれていないため、選択リストでは無効です。
これをトラブルシューティングしてくれたirc.freenode.net/#PostgreSQLのRhodiumToadに感謝します。彼はまた、この状況を解決することの難しさを指摘しています
20:33 <RhodiumToad> 1つの問題は、pgで存在できることです(select func()from ... where func()は0行を返す可能性があるSRFです)
SRFは セットを返す関数です
PostgreSQLでは、たとえばSRFを使用して1〜10のシリーズを生成できます(generate_series
はコアにあります)
SELECT * FROM generate_series(1,10);
そして、同様にここに置くことができます。
SELECT generate_series(1,10);
それらの2つを一緒に使用すると、クロス結合(デカルト積)が得られます
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を強制的にfalseに評価します。