SQL JOIN、GROUP BY 与聚合查询

JOIN、GROUP BY 与聚合函数是面试和业务查询里最常一起出现的一组 SQL 能力,关键不只是会写语法,而是理解它们各自解决什么问题以及如何配合。

#type / synthesis #status / growing #tech / dev / backend #resource / sql #resource / database

[!info] related notes

SQL JOIN、GROUP BY 与聚合查询

一句话定义

JOIN 解决“多表怎么连”,GROUP BY 解决“按什么分组”,聚合函数解决“每组怎么算”,三者合起来就是很多业务统计和列表联查题的核心。

为什么它们总是被一起问

因为真实业务查询经常不是单表直接拿数据,而是:

  • 先把用户表和订单表连起来
  • 再按用户分组
  • 最后统计每个用户有多少订单、总金额多少、最近一次下单时间是什么

所以这三件事天然经常一起出现。

先分清它们各自解决什么问题

1. JOIN

JOIN 解决的是:

多张表之间通过什么关系拼成同一条结果。

常见例子:

  • 用户表和订单表通过 user_id 关联
  • 订单表和商品表通过 product_id 关联

2. GROUP BY

GROUP BY 解决的是:

结果要按哪个维度聚成一组。

例如:

  • 按用户分组
  • 按日期分组
  • 按部门分组

3. 聚合函数

聚合函数解决的是:

每一组里到底算什么值。

最常见的有:

  • COUNT(*)
  • SUM(amount)
  • AVG(score)
  • MAX(created_at)
  • MIN(created_at)

常见 JOIN 怎么理解

1. INNER JOIN

只保留两边都能匹配上的记录。

适合:

  • 你只关心“确实有关联”的数据

2. LEFT JOIN

保留左表全部记录,右表匹配不上时补 NULL

适合:

  • 你要保留主表完整结果
  • 即使右表没有匹配数据,也要显示出来

这也是面试里非常常见的一类题,比如:

  • 查出所有用户及其订单数,包括没下过单的用户

最小例子 / 最小场景

1. 统计每个用户订单数

SELECT user_id, COUNT(*) AS order_count
FROM orders
GROUP BY user_id;

这题没有 JOIN,重点是:

  • 先按 user_id 分组
  • 再统计每组有多少行

2. 查出所有用户及其订单数,包括没下过单的用户

SELECT u.id, u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;

这题同时用到了:

  • LEFT JOIN:保留所有用户
  • GROUP BY:按用户聚合
  • COUNT(o.id):统计每个用户匹配到的订单数

最容易错的地方

1. 把 COUNT(*)COUNT(column) 混为一谈

  • COUNT(*) 统计的是组内行数
  • COUNT(column) 统计的是该列非 NULL 的行数

LEFT JOIN 场景里,这个区别尤其重要。

2. GROUP BY 后忘了非聚合列的约束

当你用了 GROUP BY:

  • 出现在 SELECT 里的非聚合列,通常也要出现在 GROUP BY

否则语义会不清楚,或者直接报错。

3. 以为 JOIN 一定会更慢

JOIN 会不会慢,不只看“用了 JOIN”,还要看:

  • 关联字段是否有索引
  • 表有多大
  • 过滤条件写在哪里
  • 查询结果是否被过度放大

从面试角度最该会什么

1. 先说清业务问题,再写 SQL

比起直接背语法,面试更稳的答法是:

  • 这题要不要保留主表全部数据
  • 要按什么维度聚合
  • 最后统计什么指标

2. 至少会这几类题

  • 每个用户有多少订单
  • 每个部门有多少员工
  • 查出没有下单的用户
  • 统计某时间范围内每天的订单数

3. 把它和性能意识连起来

写得出来只是第一步,还要知道:

  • JOIN 字段常常需要索引
  • GROUP BY 可能带来排序或聚合成本
  • 大表联查时不能只凭感觉写

进一步延伸时常一起补什么

  • 如果题目开始问“聚合前过滤还是聚合后过滤”,就接 SQL HAVING 和 WHERE 的区别
  • 如果题目变成“先查一个中间结果,再继续判断”,就接 SQL 子查询
  • 如果题目落到接口列表和大结果集返回,就接 SQL 分页

最短记忆方式

  • JOIN:表怎么连
  • GROUP BY:按什么分组
  • 聚合函数:每组怎么算
创建于 2026/5/7 更新于 2026/5/27