SQL规范是否要求EXISTS()中的GROUP BY


11

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的聊天对话

Answers:


11

我在SQL 2011规范中找到了它...

如果<select list>“ *”仅包含在<table subquery>紧接在中的a中<exists predicate>,则<select list>a等于a <value expression>是任意值<literal>

这证实了*在这种情况下不等于任意文字,实际上是PostgreSQL违反了规范。

请记住,这是一个与众不同的问题

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

这两个数据库都拒绝。

PostgreSQL,

错误:“ tx”列必须出现在GROUP BY子句中或在聚合函数中使用

SQL Server

选择列表中的“ tx”列无效,因为它既不包含在聚合函数中,也不包含在GROUP BY子句中。

为什么此错误在PostgreSQL中仍然存在

感谢irc.freenode.net/#PostgreSQL上的RhodiumToad对解决此问题提供的帮助。他还指出解决这种情况的困难

20:33 <RhodiumToad>一个问题是在pg中您可以存在(从...选择func(),其中func()是一个SRF,可能返回0行

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;

而且,这就是完全优化它的问题。您可以在EXIST语句的选择列表中包含一个SRF,该语句返回0行,并强制EXISTS评估为false。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.