GROUP BY 必须和聚合函数一起用才有效
单独写
SELECT name FROM users GROUP BY name在 MySQL 5.7+ 默认模式下会报错:
Expression #1 of SELECT list is not in GROUP BY clause。这是因为启用了
sql_mode=ONLY_FULL_GROUP_BY,它要求所有
SELECT列要么是
GROUP BY的字段,要么包裹在聚合函数里。 正确写法:用
COUNT()、
SUM()、
AVG()等处理非分组字段 临时绕过(不推荐):执行
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));,但会影响数据语义一致性 业务上真正想查的往往不是“某个 name”,而是“每个 name 对应多少条记录”这类统计结果
SELECT 列必须严格符合 GROUP BY 逻辑
比如表
orders有
user_id、
product_id、
amount三列,执行
SELECT user_id, product_id, SUM(amount) FROM orders GROUP BY user_id是非法的——因为
product_id没参与分组,MySQL 不知道该取哪一行的值。 合法写法一(按用户汇总):
SELECT user_id, COUNT(*), SUM(amount) FROM orders GROUP BY user_id合法写法二(按用户+商品组合汇总):
SELECT user_id, product_id, SUM(amount) FROM orders GROUP BY user_id, product_id如果非要查
product_id又只按
user_id分组,得用聚合函数包装,比如
MAX(product_id)或
GROUP_CONCAT(product_id),但要清楚这代表什么语义
HAVING 用来过滤分组后的结果,WHERE 不能替代
WHERE在分组前过滤行,
HAVING在分组后过滤组。例如“找出下单总额超过 1000 的用户”,必须用
HAVING:
SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id HAVING total > 1000;写成
WHERE SUM(amount) > 1000会直接报错:聚合函数不能出现在
WHERE子句中
HAVING可以引用
SELECT中的别名(如
total),但部分旧版 MySQL 要求写完整表达式
SUM(amount) > 1000性能上,先
WHERE再
GROUP BY再
HAVING是最优顺序,避免对无意义的数据分组
NULL 值在 GROUP BY 中会被当作同一组
如果
user_id允许为
NULL,那么所有
NULL值会聚合成一组。比如:
SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;
结果里可能出现一行
NULL | 5,表示有 5 条记录的
user_id是空值。 需要区分“未填”和“已填但值为 0”时,建议用确定值(如
0或
-1)代替
NULL,或加条件
WHERE user_id IS NOT NULL排序时
NULL默认排最前(
ASC)或最后(
DESC),但分组行为本身不依赖排序 多字段
GROUP BY a, b时,只要任一字段为
NULL,就按
NULL处理,不会因另一字段不同而拆开 实际写
GROUP BY时,最容易忽略的是字段语义是否真的可聚合——比如对时间字段用
MIN(created_at)和
MAX(created_at)很自然,但对用户名用
AVG(name)就毫无意义。分组逻辑必须从业务目标出发,而不是语法能跑通就完事。
