mysql - 为什么此代码能够在 HAVING 中使用来自 SELECT 的别名?

标签 mysql sql group-by count having-clause

我在网上找到了这个解决方案 HackerRank problem :

SELECT c.hacker_id, h.name, COUNT(c.challenge_id) AS cnt 
FROM Hackers AS h 
JOIN Challenges AS c ON h.hacker_id = c.hacker_id
GROUP BY c.hacker_id, h.name 
HAVING
    cnt = (SELECT COUNT(c1.challenge_id) FROM Challenges AS c1 GROUP BY c1.hacker_id ORDER BY COUNT(*) DESC LIMIT 1) OR
    cnt NOT IN (SELECT COUNT(c2.challenge_id) FROM Challenges AS c2 GROUP BY c2.hacker_id HAVING c2.hacker_id <> c.hacker_id)
ORDER BY cnt DESC, c.hacker_id;

可以看到,cnt是在SELECT中定义的,然后在HAVING中使用。我的理解是,从逻辑上讲,GROUP BY 和 HAVING 在 SELECT 之前运行。因此,我希望 SQL 在执行 GROUP BY 时不会识别 cnt,并抛出错误。但是,代码给出了正确的解决方案。

谁能解释一下为什么?也许 MySQL 会人为地对此进行更正?

最佳答案

您假设 SELECT 子句中定义的别名不能在 HAVING 子句中使用是通常正确的:这在标准中是不允许的SQL(也称为 ANSI SQL),大多数数据库不允许这样做。

然而,MySQL 扩展了标准,如解释的那样in the documentation :

The MySQL extension permits the use of an alias in the HAVING clause for the aggregated column.

因此您显示的代码不是有效的 ANSI SQL,但它是有效的 MySQL 查询。 MySQL 实现了对 ANSI SQL 的许多其他扩展,这些扩展在链接文档中进行了描述。

更一般地说,据我所知,没有一个数据库是完全严格遵守 ANSI 规范的。它们都缺少功能和扩展。学习 SQL,您还需要了解您正在运行的数据库的特性。

关于mysql - 为什么此代码能够在 HAVING 中使用来自 SELECT 的别名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64395734/

相关文章:

java - 如何在Java命名参数jdbc模板批量更新插入查询中映射具有特殊字符的列?

mysql - sql 查询返回太多结果和重复项

mysql - 调用 DriverManager.getConnection() 时出现意外的 java.lang.NoClassDefFoundError

java - JDBC 的 rs.getString() 不会返回查询结果的值

php - 使用第一个查询中的变量从第二个查询中获取结果时出错

PHP 用链接分隔逗号列表

sql - 数据库项目可以使用 machine.config 连接字符串进行部署吗?

python - 使用 Pandas 将 groupby 聚合应用于原始数据框

SQL - 按 ID 分组和从变量起点开始的时间间隔

sql - 分组 : SQL 时始终获取用户的最新记录