SQL新手技术问询:HAVING子句执行逻辑与*1.0作用的疑问
嘿,作为同样摸爬滚打过的SQL新手,我来给你拆解这两个问题:
1. 为什么需要乘以1.0?
在大多数SQL数据库(比如MySQL、PostgreSQL、SQL Server等)里,整数之间的除法会执行「整数除法」——也就是结果会直接舍去小数部分,只保留整数。举个例子:如果某赛季非平局比赛的总进球数是7,比赛场数是3,7/3得到的结果会是2,而不是你想要的2.333...
乘以1.0的作用是把其中一个操作数转换成浮点数(或者说数值型),这样整个除法运算就会按照浮点数规则计算,得到带小数的精确结果。如果没有这个转换,你后面用round(...,3)去保留三位小数也没意义,因为整数除法已经把小数部分丢掉了。
你也可以用其他方式实现同样的效果,比如cast(sum(home_team_goal+away_team_goal) as decimal),不过乘以1.0是更简洁的写法。
2. 为什么having子句能使用select里定义的ratio别名?
你说的SQL逻辑执行顺序from→where→group→having→select是没错的,但这里有个实用的例外:很多现代数据库的查询优化器允许在having子句中引用select里定义的别名。
本质上,数据库会在执行阶段把having ratio > 1里的ratio替换成它对应的完整表达式:round((sum(home_team_goal+away_team_goal) *1.0) /count(id),3),相当于你直接把整个计算式写在having里。不过要注意,这不是SQL标准里的强制要求,有些严格遵循标准的数据库(比如Oracle的旧版本)可能不支持这种写法,这时候你就需要把完整表达式重复写在having里,或者用子查询封装。
好在大多数常用的数据库都支持这种别名引用,大大简化了代码的可读性。
内容的提问来源于stack exchange,提问作者EMsql

