SQL - 使用 'HAVING' 和 'EXISTS' 而不使用 'GROUP BY'

SQL - using 'HAVING' with 'EXISTS' without using 'GROUP BY'

不允许在没有 'GROUP BY' 的情况下使用 'HAVING':

SELECT *
FROM products
HAVING unitprice > avg(unitprice)

列 'products.UnitPrice' 在 HAVING 子句中无效,因为它未包含在聚合函数或 GROUP BY 子句中。

但是将相同的代码放在 'EXISTS' 下时 - 没有问题:

SELECT *
FROM products p
WHERE EXISTS (SELECT 1
              FROM products
              HAVING p.unitprice > avg(unitprice))

你能解释一下为什么吗?

HAVING 根据 SQL 标准和大多数数据库过滤 after 聚合。

没有GROUP BY,仍然存在聚合。

但在您的情况下,您只需要一个子查询和 WHERE:

SELECT p.*
FROM products p
WHERE p.unitprice > (SELECT AVG(p2.unitprice) FROM products p2);

好吧,第一个查询中的错误很明显 UnitPrice 不是聚合的一部分,也不是分组依据 而在您的第二个查询中,您正在比较 p.unitprice 来自 table“产品 p”,它不需要成为聚合或分组依据的一部分,您的第二个查询等同于:

select * from products p
where p.unitprice > (select avg(unitprice) FROM products)

这可能更清楚,sql 计算 avg(unitprice) 然后将其与产品中的 unitprice 列进行比较。

问题出在您 select 的列中:

SELECT *

SELECT 1

与在每一行计算的普通函数不同,聚合函数是在处理整个数据集后计算的,这意味着理论上(至少没​​有 GROUP BY 语句),您不能 select同一列集中的聚合函数和常规函数(即使某些 DBMS 仍然容忍这种情况)。

考虑 SUM() 时更容易看出。在返回所有行之前,您不应该访问列的总数,这会阻止您编写类似 SELECT price,SUM(price) 的内容。

GROUP BY,现在,您可以根据给定的条件(实际上是一堆列)对行进行重新分组,这使得这些聚合函数可以在每个组的末尾进行计算整个数据集的。因此,由于在 GROUP BY 中指定的所有列对于给定组来说应该是相同的,因此您可以将它们包含在全局 SELECT 语句中。

这使我们找到了实际的失败原因:在第一次查询时,您 select 所有列。在第二个,你 select none: 只有常量 1,它不是 table 本身的一部分。