Skip to content

2026-08-29 · MySQL 学习笔记 04

MySQL 查询进阶:排序、分页、聚合、分组

沿用商品表示例:

sql
CREATE TABLE goods (
  id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
  name VARCHAR(50) NOT NULL COMMENT '商品名',
  price DECIMAL(10,2) NOT NULL COMMENT '单价',
  stock INT NOT NULL DEFAULT 0 COMMENT '库存',
  category VARCHAR(20) COMMENT '分类',
  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) COMMENT '商品表';

1. 排序 ORDER BY

sql
-- 升序(默认,小到大)
SELECT * FROM goods ORDER BY price;

-- 降序(大到小)
SELECT * FROM goods ORDER BY price DESC;

-- 多列:先按分类,分类内按价格降序
SELECT * FROM goods ORDER BY category, price DESC;

-- 按别名排序
SELECT name AS 商品名, price AS 单价 FROM goods ORDER BY 单价 DESC;

ASC 是升序关键词,默认就是升序,可以不写;DESC 降序必须写。

2. 分页 LIMIT

后端列表页翻页用这个:

sql
-- 跳过 0 条取 2 条(第 1 页)
SELECT * FROM goods LIMIT 2 OFFSET 0;

-- 跳过 2 条取 2 条(第 2 页)
SELECT * FROM goods LIMIT 2 OFFSET 2;

另一个等价写法(MySQL 专用,OFFSET 放前面):

sql
SELECT * FROM goods LIMIT 2, 2;   -- 从第 2 条起取 2 条

页码换算公式:OFFSET = (页码 - 1) × 每页条数。第 3 页每页 2 条 → LIMIT 2 OFFSET 4

通常配合排序用,让分页顺序稳定:

sql
SELECT * FROM goods ORDER BY id DESC LIMIT 2 OFFSET 0;

3. 聚合函数

把多行算成一个数:

sql
SELECT COUNT(*) FROM goods;              -- 总行数:5
SELECT COUNT(category) FROM goods;       -- 非空 category 的数量
SELECT SUM(stock) FROM goods;            -- 库存总和
SELECT AVG(price) FROM goods;            -- 均价
SELECT MAX(price), MIN(price) FROM goods; -- 最高价、最低价

COUNT(*) 数行数;COUNT(某列) 数该列非空的行数,两者结果可能不同。

起个名字好认:

sql
SELECT COUNT(*) AS 商品总数 FROM goods;

去重计数:

sql
SELECT COUNT(DISTINCT category) FROM goods;   -- 有几个分类:3

4. 分组 GROUP BY

按某列的值把行分成几组,再配聚合函数算每组:

sql
-- 每个分类有几个商品
SELECT category, COUNT(*) AS 数量 FROM goods GROUP BY category;

-- 每个分类的库存合计
SELECT category, SUM(stock) AS 库存合计 FROM goods GROUP BY category;

-- 每个分类的最高价、最低价
SELECT category, MAX(price) AS 最高价, MIN(price) AS 最低价
FROM goods GROUP BY category;

分组关键字顺序固定:

sql
SELECT ... FROM ... WHERE ... GROUP BY ... ORDER BY ... LIMIT ...

先 WHERE 过滤,后分组

sql
-- 只统计价格 3 元以上的商品,按分类分组
SELECT category, COUNT(*) AS 数量 FROM goods
WHERE price > 3
GROUP BY category;

5. 分组后过滤 HAVING

WHERE 不能用在聚合结果上(WHERE 在分组前执行,聚合是分组后的事),分组后过滤用 HAVING:

sql
-- 找出商品数 >= 2 的分类
SELECT category, COUNT(*) AS cnt
FROM goods
GROUP BY category
HAVING cnt >= 2;

6. 一个综合例子(列表页统计)

sql
SELECT category, COUNT(*) AS 商品数, SUM(stock) AS 库存
FROM goods
WHERE price > 2
GROUP BY category
HAVING 商品数 >= 2
ORDER BY 库存 DESC;

顺序:WHERE(行过滤)→ GROUP BY(分组)→ HAVING(组过滤)→ ORDER BY(排序)→ LIMIT(分页)