【问题标题】:SQL - using 'HAVING' with 'EXISTS' without using 'GROUP BY'SQL - 使用 'HAVING' 和 'EXISTS' 而不使用 'GROUP BY'
【发布时间】:2021-05-03 20:42:18
【问题描述】:

不允许使用不带“GROUP BY”的“HAVING”:

SELECT *
FROM products
HAVING unitprice > avg(unitprice)

HAVING 子句中的“products.UnitPrice”列无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

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

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

你能解释一下原因吗?

【问题讨论】:

  • 您使用的是哪种数据库产品?这感觉就像在 mysql 中发生的一些愚蠢的废话。我的猜测是,您的子查询的 products.unitprice 的平均聚合是推断出来的,因为它是子查询的 products 表中使用的唯一列(其他提到的列是 p.unitprice1 两者都不在该表中) .在您的第一个查询中,您在同一条件语句中要求平均聚合和非聚合unitprice,而不使用窗口函数。
  • “不允许在没有 'GROUP BY' 的情况下使用 'HAVING'”——这可能是您的印象,但这是错误的。不允许在HAVING 子句中使用既不是HAVING 子句中聚合函数的参数也不是GROUP BY 子句中列出的列(或任何使用此类列的表达式)。 SELECT BTW 之后列出的列也是如此。例如。试试SELECT avg(unitprice) FROM products HAVING avg(unitprice) > 0;

标签: sql exists having


【解决方案1】:

第一个查询中的错误很明显 UnitPrice 不是聚合的一部分,也不是分组依据 而在您的第二个查询中,您正在比较不需要属于聚合或分组依据的表“products p”中的 p.unitprice,您的第二个查询相当于:

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

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

【讨论】:

    【解决方案2】:

    HAVING 根据 SQL 标准和在大多数数据库中过滤之后聚合。

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

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

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

    【讨论】:

      【解决方案3】:

      问题来自您选择的列:

      SELECT *
      

      SELECT 1
      

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

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

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

      这将我们引向实际的失败原因:在第一次查询时,您选择了所有列。在第二个中,您选择 none:只选择常量 1,它不是表本身的一部分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-13
        • 2016-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多