一、ORDER BY:让数据有序排列
1.1 基础语法与单列排序
sql
SELECT 列名1, 列名2, ...
FROM 表名
ORDER BY 排序列 [ASC | DESC];
示例1:基本升序排序
sql
— 创建示例表:学生成绩表
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50),
class VARCHAR(20),
chinese_score INT,
math_score INT,
english_score INT,
total_score INT,
birthday DATE
);
INSERT INTO students VALUES
(1, '张三', '一班', 85, 92, 78, 255, '2005-03-15'),
(2, '李四', '二班', 92, 88, 90, 270, '2005-07-22'),
(3, '王五', '一班', 78, 85, 92, 255, '2005-11-05'),
(4, '赵六', '二班', 65, 72, 68, 205, '2005-01-30'),
(5, '孙七', '一班', 88, 94, 87, 269, '2005-06-18'),
(6, '周八', '二班', 95, 89, 93, 277, '2005-09-10');
— 按总分降序排列
SELECT
id AS '学号',
name AS '姓名',
total_score AS '总分'
FROM students
ORDER BY total_score DESC;
查询结果:
text
学号 姓名 总分
6 周八 277
2 李四 270
5 孙七 269
1 张三 255
3 王五 255
4 赵六 205
示例2:多列排序
sql
— 先按班级排序,再按总分降序排序
SELECT
name AS '姓名',
class AS '班级',
total_score AS '总分',
chinese_score AS '语文',
math_score AS '数学',
english_score AS '英语'
FROM students
ORDER BY class ASC, total_score DESC;
查询结果:
text
姓名 班级 总分 语文 数学 英语
孙七 一班 269 88 94 87
张三 一班 255 85 92 78
王五 一班 255 78 85 92
周八 二班 277 95 89 93
李四 二班 270 92 88 90
赵六 二班 205 65 72 68
1.2 高级排序技巧
使用表达式排序
sql
— 按平均分排序
SELECT
name,
chinese_score,
math_score,
english_score,
(chinese_score + math_score + english_score) / 3 AS average_score
FROM students
ORDER BY (chinese_score + math_score + english_score) / 3 DESC;
使用函数排序
sql
— 按名字长度排序
SELECT
name,
LENGTH(name) AS name_length,
class
FROM students
ORDER BY LENGTH(name) DESC;
自定义排序顺序
sql
— 按班级自定义顺序排序(先二班,后一班)
SELECT
name,
class,
total_score
FROM students
ORDER BY
CASE class
WHEN '二班' THEN 1
WHEN '一班' THEN 2
ELSE 3
END,
total_score DESC;
1.3 NULL值处理
sql
— 创建包含NULL值的示例
CREATE TABLE employees (
id INT,
name VARCHAR(50),
salary DECIMAL(10,2),
commission DECIMAL(10,2)
);
INSERT INTO employees VALUES
(1, '张三', 8000, 2000),
(2, '李四', 9500, NULL),
(3, '王五', 7500, 1500),
(4, '赵六', 8800, NULL);
— NULL值默认排在最后(升序时)
SELECT * FROM employees ORDER BY commission ASC;
— 让NULL值排在最前
SELECT * FROM employees
ORDER BY
CASE WHEN commission IS NULL THEN 0 ELSE 1 END,
commission ASC;
二、GROUP BY与HAVING:数据分组与筛选
2.1 GROUP BY基础语法
sql
SELECT
分组列,
聚合函数(列名)
FROM 表名
GROUP BY 分组列
[HAVING 分组条件];
常用聚合函数 
2.2 基础分组查询示例
示例1:按班级分组统计
sql
— 统计每个班级的学生人数、平均分、最高分、最低分
SELECT
class AS '班级',
COUNT(*) AS '学生人数',
AVG(total_score) AS '平均总分',
MAX(total_score) AS '最高分',
MIN(total_score) AS '最低分',
SUM(total_score) AS '总分合计'
FROM students
GROUP BY class;
查询结果:
text
班级 学生人数 平均总分 最高分 最低分 总分合计
一班 3 259.67 269 255 779
二班 3 250.67 277 205 752
示例2:多列分组
sql
— 创建销售记录表
CREATE TABLE sales (
sale_id INT PRIMARY KEY,
sale_date DATE,
product_name VARCHAR(50),
category VARCHAR(30),
salesperson VARCHAR(50),
quantity INT,
unit_price DECIMAL(10,2),
region VARCHAR(20)
);
INSERT INTO sales VALUES
(1, '2023-10-01', '笔记本电脑', '电子产品', '张三', 2, 6999.00, '北京'),
(2, '2023-10-01', '智能手机', '电子产品', '李四', 5, 2999.00, '上海'),
(3, '2023-10-02', '办公椅', '家具', '王五', 3, 599.00, '北京'),
(4, '2023-10-02', '笔记本电脑', '电子产品', '张三', 1, 6999.00, '广州'),
(5, '2023-10-03', '智能手机', '电子产品', '李四', 3, 2999.00, '北京'),
(6, '2023-10-03', '显示器', '电子产品', '赵六', 4, 1599.00, '上海'),
(7, '2023-10-04', '办公桌', '家具', '王五', 2, 1299.00, '广州');
— 按产品和地区分组统计
SELECT
product_name AS '产品名称',
region AS '地区',
COUNT(*) AS '销售笔数',
SUM(quantity) AS '总销量',
SUM(quantity * unit_price) AS '总销售额',
AVG(unit_price) AS '平均单价'
FROM sales
GROUP BY product_name, region;
2.3 HAVING子句:分组后的筛选

示例1:筛选分组结果
sql
— 查找平均分大于260的班级
SELECT
class,
COUNT(*) AS student_count,
AVG(total_score) AS avg_score
FROM students
GROUP BY class
HAVING AVG(total_score) > 260;
— 查找销售总额超过10000的产品
SELECT
product_name,
SUM(quantity * unit_price) AS total_sales
FROM sales
GROUP BY product_name
HAVING SUM(quantity * unit_price) > 10000;
示例2:复杂的HAVING条件
sql
— 查找满足多个条件的销售分组
SELECT
region AS '地区',
category AS '类别',
COUNT(*) AS '订单数',
SUM(quantity * unit_price) AS '总销售额'
FROM sales
GROUP BY region, category
HAVING
SUM(quantity * unit_price) > 5000
AND COUNT(*) >= 2
ORDER BY SUM(quantity * unit_price) DESC;
示例3:WHERE与HAVING组合使用
sql
— 先筛选,再分组,再筛选
SELECT
salesperson AS '销售员',
region AS '地区',
COUNT(*) AS '订单数量',
SUM(quantity * unit_price) AS '销售总额'
FROM sales
WHERE sale_date BETWEEN '2023-10-01' AND '2023-10-03' — 先按日期筛选
GROUP BY salesperson, region
HAVING SUM(quantity * unit_price) > 5000 — 再按总额筛选
ORDER BY SUM(quantity * unit_price) DESC;
2.4 高级分组技巧
使用GROUP_CONCAT合并分组数据
sql
— 查询每个班级的学生名单
SELECT
class AS '班级',
GROUP_CONCAT(name ORDER BY total_score DESC SEPARATOR ', ') AS '学生名单',
AVG(total_score) AS '班级平均分'
FROM students
GROUP BY class;
查询结果:
text
班级 学生名单 班级平均分
一班 孙七, 张三, 王五 259.67
二班 周八, 李四, 赵六 250.67
按日期分组统计
sql
— 按日期统计销售额
SELECT
DATE_FORMAT(sale_date, '%Y-%m-%d') AS '销售日期',
COUNT(*) AS '订单数量',
SUM(quantity) AS '总销量',
SUM(quantity * unit_price) AS '日销售额'
FROM sales
GROUP BY sale_date
ORDER BY sale_date;
使用ROLLUP生成小计
sql
— 生成带小计的分组统计
SELECT
IFNULL(region, '所有地区') AS '地区',
IFNULL(category, '所有类别') AS '产品类别',
COUNT(*) AS '订单数',
SUM(quantity * unit_price) AS '销售额'
FROM sales
GROUP BY region, category WITH ROLLUP
ORDER BY region, category;
三、LIMIT:限制结果集数量
3.1 基础语法
sql
— 格式1:限制返回的行数
SELECT * FROM 表名 LIMIT 数量;
— 格式2:指定偏移量
SELECT * FROM 表名 LIMIT 偏移量, 数量;
— 或者
SELECT * FROM 表名 LIMIT 数量 OFFSET 偏移量;
3.2 分页查询应用
示例1:基本分页
sql
— 每页显示3条记录
— 第1页
SELECT * FROM students
ORDER BY total_score DESC
LIMIT 0, 3;
— 第2页
SELECT * FROM students
ORDER BY total_score DESC
LIMIT 3, 3;
— 使用OFFSET语法
SELECT * FROM students
ORDER BY total_score DESC
LIMIT 3 OFFSET 3;
示例2:分页参数化
sql
— 创建分页存储过程
DELIMITER $$
CREATE PROCEDURE get_students_by_page(
IN page_num INT, — 页码
IN page_size INT — 每页大小
)
BEGIN
DECLARE offset_val INT;
SET offset_val = (page_num – 1) * page_size;
SELECT
name,
class,
total_score
FROM students
ORDER BY total_score DESC
LIMIT offset_val, page_size;
END$$
DELIMITER ;
— 调用:获取第2页,每页3条
CALL get_students_by_page(2, 3);
3.3 TOP N查询
示例1:查询前N名
sql
— 查询总分前三名的学生
SELECT
name,
total_score,
class
FROM students
ORDER BY total_score DESC
LIMIT 3;
— 查询每个班级的前两名
SELECT
name,
class,
total_score
FROM students
WHERE (
SELECT COUNT(*)
FROM students AS s2
WHERE s2.class = students.class
AND s2.total_score >= students.total_score
) <= 2
ORDER BY class, total_score DESC;
示例2:百分比查询
sql
— 查询前50%的学生(假设有6个学生,取前3名)
SELECT
name,
total_score
FROM students
ORDER BY total_score DESC
LIMIT (SELECT COUNT(*) FROM students) / 2;
3.4 随机抽样
sql
— 随机抽取3个学生
SELECT
name,
total_score
FROM students
ORDER BY RAND()
LIMIT 3;
四、综合应用案例
4.1 电商数据分析报表
sql
— 创建完整的电商数据分析查询
SELECT
DATE_FORMAT(sale_date, '%Y年%m月') AS '销售月份',
region AS '销售地区',
category AS '产品类别',
COUNT(DISTINCT salesperson) AS '销售员人数',
COUNT(*) AS '订单数量',
SUM(quantity) AS '销售总量',
SUM(quantity * unit_price) AS '销售总额',
AVG(unit_price) AS '平均单价',
MAX(quantity * unit_price) AS '最大单笔订单',
MIN(unit_price) AS '最低单价'
FROM sales
WHERE sale_date >= '2023-01-01'
GROUP BY
DATE_FORMAT(sale_date, '%Y-%m'),
region,
category
HAVING
SUM(quantity * unit_price) > 1000
AND COUNT(*) >= 1
ORDER BY
DATE_FORMAT(sale_date, '%Y-%m') DESC,
SUM(quantity * unit_price) DESC
LIMIT 20;
4.2 学生成绩分析系统
sql
— 学生成绩综合统计
WITH class_stats AS (
SELECT
class,
COUNT(*) AS total_students,
AVG(total_score) AS class_avg,
MAX(total_score) AS class_max,
MIN(total_score) AS class_min
FROM students
GROUP BY class
),
student_rank AS (
SELECT
name,
class,
total_score,
RANK() OVER (PARTITION BY class ORDER BY total_score DESC) AS class_rank,
RANK() OVER (ORDER BY total_score DESC) AS overall_rank
FROM students
)
SELECT
s.name AS '姓名',
s.class AS '班级',
s.total_score AS '总分',
sr.class_rank AS '班级排名',
sr.overall_rank AS '全校排名',
cs.class_avg AS '班级平均分',
CASE
WHEN s.total_score >= cs.class_avg THEN '高于平均'
ELSE '低于平均'
END AS '与班级平均分比较'
FROM students s
JOIN student_rank sr ON s.name = sr.name
JOIN class_stats cs ON s.class = cs.class
ORDER BY
s.class,
s.total_score DESC
LIMIT 10;
五、性能优化建议
5.1 ORDER BY优化
sql
— 1. 为ORDER BY列创建索引
CREATE INDEX idx_total_score ON students(total_score);
— 2. 避免使用表达式排序(如果可能)
— 优化前
SELECT * FROM students ORDER BY total_score + 10 DESC;
— 优化后
SELECT *, total_score + 10 AS adjusted_score
FROM students
ORDER BY total_score DESC;
— 3. 使用覆盖索引
— 优化前
SELECT name, class FROM students ORDER BY total_score;
— 优化后(创建复合索引)
CREATE INDEX idx_covering ON students(total_score, name, class);
5.2 GROUP BY优化
sql
— 1. 使用EXPLAIN分析
EXPLAIN SELECT class, COUNT(*) FROM students GROUP BY class;
— 2. 减少分组列的数量
— 优化前
SELECT class, YEAR(birthday), COUNT(*) FROM students GROUP BY class, YEAR(birthday);
— 优化后
SELECT class, COUNT(*) FROM students GROUP BY class;
— 3. 在WHERE中过滤,减少GROUP BY数据量
SELECT class, AVG(total_score)
FROM students
WHERE total_score > 200 — 先过滤
GROUP BY class;
5.3 LIMIT优化
sql
— 1. 使用有索引的列进行ORDER BY
— 慢
SELECT * FROM students ORDER BY name LIMIT 100000, 20;
— 快(如果id是主键)
SELECT * FROM students ORDER BY id LIMIT 100000, 20;
— 2. 使用子查询优化深分页
— 优化前(深分页效率低)
SELECT * FROM students ORDER BY id LIMIT 100000, 20;
— 优化后
SELECT * FROM students
WHERE id >= (SELECT id FROM students ORDER BY id LIMIT 100000, 1)
ORDER BY id
LIMIT 20;
网硕互联帮助中心





评论前必须登录!
注册