SQL中GROUP BY子句的使用必要性及分组原理解析
SQL聚合查询中GROUP BY的核心逻辑解答
为什么查询中需要使用GROUP BY执行分组
SQL的聚合函数(count/avg/sum/max/min等)本质是对一个数据集合做计算返回单个结果,如果你的查询同时需要返回原始维度字段和聚合计算结果,就必须通过GROUP BY明确告诉数据库:你要把全表数据拆成多少个独立的小集合,每个小集合单独跑聚合计算,最终每个集合返回一行结果。
如果不加GROUP BY,数据库会默认把全表所有数据当成一个集合做聚合,最终只会返回一行全表总统计值,没法拆分出不同维度下的细分统计结果。另外标准SQL有个强制规则:除了被聚合函数包裹的字段,SELECT子句里出现的所有非聚合字段,必须全部写在GROUP BY子句里,否则数据库无法判断这些非聚合字段应该按什么粒度取值,会直接抛出语法错误。
分组操作的划分维度规则
GROUP BY是严格按照你在子句后列出的字段/表达式的唯一值组合来切分数据的:只要某几行数据在你列出的所有分组维度上的值完全一致,就会被归到同一个组里做聚合计算。
结合你提供的BigQuery练习代码做具体说明:
SELECT usertype, concat(start_station_name, " to ", end_station_name) AS route, count (*) AS num_trips, --counting all trips (gives distinct value?) Round(AVG(Cast(tripduration AS int64)/60),2) AS duration --/60 to make into minutes not seconds and the 2 is for decimal place FROM `bigquery-public-data.new_york_citibike.citibike_trips` GROUP BY start_station_name, end_station_name, usertype Order by num_trips desc LIMIT 10
- 这段代码的分组维度是三个:用户类型
usertype、起点站名称start_station_name、终点站名称end_station_name,所有「用户类型相同、起点站相同、终点站相同」的行程记录会被归为同一个组 - 每个组独立计算两个聚合值:组内总行程数
num_trips、组内平均骑行时长duration(秒转分钟后保留两位小数) - 你代码注释里的疑问解答:
count(*)是统计当前组内的所有总行数,不会做去重,要实现去重计数需要使用count(DISTINCT 字段名)语法 - 额外说明:你在SELECT里拼接生成的
route字段没有写在GROUP BY里但没报错,是BigQuery做了函数依赖识别——只要起点站、终点站确定,拼接出来的路线值就是唯一的,所以不会触发语法错误,但在PostgreSQL、开启严格模式的MySQL等其他SQL方言中,这类由分组字段推导出来的表达式也需要写在GROUP BY中才能正常运行 - 这段代码最终返回的结果,就是纽约Citi Bike骑行数据里,按用户类型、骑行路线分组后,总行程量最高的前10条路线及对应平均骑行时长。
内容的提问来源于stack exchange,提问作者data_rfb
相关产品推荐
相关产品推荐

