【问题标题】:Why can HAVING reference COUNT(column_name) but not the column_name itself?为什么 HAVING 可以引用 COUNT(column_name) 而不是 column_name 本身?
【发布时间】:2020-05-29 19:42:50
【问题描述】:

我试图更好地理解 MySQL 的工作原理。我遇到了子组的问题。从问题Unknown column in 'having clause',我明白了为什么这段代码会返回错误:

SELECT b.Title, b.Isbn
FROM Book AS b
INNER JOIN Writing AS w ON w.Book_id = b.ID
GROUP BY b.ID
HAVING w.Author_id = 1 AND b.Title LIKE "%Head%"

那个错误是:“‘有子句’中的未知列‘w.Author_id’”,因为:

SQL 标准要求 HAVING 必须仅引用 GROUP BY 子句中的列或聚合函数中使用的列。但是,MySQL 支持对此行为的扩展,并允许 HAVING 引用 SELECT 列表中的列以及外部子查询中的列。

但是,如果我使用COUNT(w.Author_id) > 1 而不是w.Author_id = 1,则代码可以正常运行:

SELECT b.Title, b.Isbn
FROM Book AS b
INNER JOIN Writing AS w ON w.Book_id = b.ID
GROUP BY b.ID
HAVING COUNT(w.Author_id) > 1 AND b.Title LIKE "%Head%"

所以,我的问题是:COUNT() 是什么让 w.Author_id 可以访问?如果这是一个愚蠢/明显的问题,我深表歉意 - 我还是 SQL 的新手。

【问题讨论】:

  • COUNT() 无法访问,它使语法落后于逻辑。 w.Author_id=1 和 count(w.Author_id)= 1 这两个条件完全不同。如果要添加条件 w.Author_id=1 则可以在 where 子句中使用。在拥有子句中,您应该使用分组字段或聚合函数。

标签: mysql sql


【解决方案1】:

关于这个主题的文档似乎很清楚。但是让我看看能不能更好地为你解释一下。

HAVING 子句本质上是WHERE 子句,在GROUP BY 之后“发生”。即聚合已经发生,所以可用的数据是聚合数据。

在您的示例中,聚合没有返回 Author_Id。而 MySQL 不知道如何生成一个。

但是,COUNT(w.Author_Id) 是一个汇总结果。 MySQL 可以(从概念上)将其添加到聚合返回的结果中并对其进行过滤。

您的查询相当于:

SELECT Title, Isbn
FROM (SELECT b.Title, b.Isbn, COUNT(*) as cnt
      FROM Book b JOIN
           Writing w
           ON w.Book_id = b.ID
      GROUP BY b.ID
     ) b
WHERE cnt > 1 AND b.Title LIKE '%Head%';

也就是说,查询最好写成:

SELECT b.Title, b.Isbn
FROM Book b JOIN
     Writing w
     ON w.Book_id = b.ID
WHERE b.Title LIKE '%Head%'
GROUP BY b.ID
HAVING COUNT(*) > 1;

您可以在聚合之前对title 进行过滤,这通常效率更高。

【讨论】:

    【解决方案2】:

    当您将w.Author_id 放在表达式COUNT(w.Author_id) > 1 中时,您就满足了HAVING 子句的要求

    HAVING 必须仅引用 GROUP BY 子句中的列或聚合函数中使用的列

    而单独的 ID 列不会,因为它不是 GROUP BY 子句的一部分,也不在聚合函数中(COUNT 是)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多