我在网上找到了这个解决方案 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/