📊 SQL 入门 Day 2:排序与去重 — 让数据有序呈现

学会排序和去重,告别杂乱无章的查询结果。

📝 知识点简介

查询数据很容易,但查出来的结果往往是无序 的。要让数据按你想要的顺序排列,或者去除重复行,就需要掌握 ORDER BYDISTINCT。这两个看似简单的语法,实际使用中有不少细节坑。


一、ORDER BY --- 排序

1. 基本语法

sql 复制代码
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
  • ASC:升序(默认,可省略)
  • DESC:降序

2. 单列排序

sql 复制代码
-- 按薪水升序排列(ASC 可省略)
SELECT emp_name, salary
FROM employees
ORDER BY salary;

-- 按薪水降序排列
SELECT emp_name, salary
FROM employees
ORDER BY salary DESC;

3. 多列排序

先按第一列排,相同值时按第二列排:

sql 复制代码
-- 先按部门升序,再按薪水降序
SELECT dept_id, emp_name, salary
FROM employees
ORDER BY dept_id ASC, salary DESC;

执行结果示意:

diff 复制代码
dept_id | emp_name | salary
--------|----------|-------
1       | 张三     | 15000
1       | 李四     | 12000
1       | 王五     | 12000
2       | 赵六     | 18000
2       | 钱七     | 10000

4. 按表达式/别名排序

sql 复制代码
-- 按计算字段排序
SELECT emp_name, salary, salary * 1.1 AS new_salary
FROM employees
ORDER BY new_salary DESC;

-- 按函数结果排序
SELECT emp_name, hire_date
FROM employees
ORDER BY EXTRACT(YEAR FROM hire_date);

5. 按列位置排序(不推荐)

某些数据库支持按 SELECT 中的列序号排序:

sql 复制代码
SELECT emp_name, salary, hire_date
FROM employees
ORDER BY 2 DESC;  -- 等价于 ORDER BY salary DESC

⚠️ 建议:使用列名而非序号,可读性更好,且修改 SELECT 列时不会意外改变排序行为。

6. NULL 值的排序

NULL 的排序位置因数据库而异:

数据库 NULL 默认排在 控制方式
MySQL 升序排前面,降序排后面 无标准语法
PostgreSQL 升序排后面,降序排前面 NULLS FIRST / NULLS LAST
SQL Server 升序排前面,降序排前面 无标准语法
Oracle 升序排后面,降序排前面 NULLS FIRST / NULLS LAST
sql 复制代码
-- PostgreSQL / Oracle:把 NULL 排到最后
SELECT emp_name, bonus
FROM employees
ORDER BY bonus DESC NULLS LAST;

二、LIMIT / OFFSET --- 分页与限制

1. MySQL / PostgreSQL

sql 复制代码
-- 取前 5 条
SELECT * FROM employees ORDER BY salary DESC LIMIT 5;

-- 跳过前 5 条,取接下来的 5 条(第 6-10 条)
SELECT * FROM employees ORDER BY salary DESC LIMIT 5 OFFSET 5;

简写形式(MySQL, PostgreSQL):

sql 复制代码
SELECT * FROM employees ORDER BY salary DESC LIMIT 5, 5;
-- 含义:LIMIT 偏移量, 条数(⚠️ 和上面的 OFFSET 写法参数顺序相反)

2. SQL Server / PostgreSQL FETCH

sql 复制代码
-- SQL Server / PostgreSQL 标准语法
SELECT emp_name, salary
FROM employees
ORDER BY salary DESC
OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY;

-- 第 2 页(第 6-10 条)
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY;

3. ORDER BY 在分页中的重要性

sql 复制代码
-- ❌ 危险!无 ORDER BY 的分页结果不确定
SELECT * FROM employees LIMIT 10 OFFSET 0;
SELECT * FROM employees LIMIT 10 OFFSET 10;
-- 两页之间可能有重复/遗漏

-- ✅ 必须加 ORDER BY,且排序列要唯一
SELECT * FROM employees
ORDER BY emp_id
LIMIT 10 OFFSET 0;

SELECT * FROM employees
ORDER BY emp_id
LIMIT 10 OFFSET 10;

⚠️ 分页必知ORDER BY 的列如果有重复值,同一行可能出现在不同页。最佳实践 :用 id + created_at 等唯一组合排序。


三、DISTINCT --- 去重

1. 单列去重

sql 复制代码
-- 查询所有不重复的部门
SELECT DISTINCT dept_id
FROM employees;

2. 多列去重

sql 复制代码
-- 查询所有不重复的(部门, 职位)组合
SELECT DISTINCT dept_id, job_title
FROM employees;

DISTINCT 作用于所有选中的列的组合,只有当所有列的值都相同时才视为重复。

3. DISTINCT 与聚合函数

sql 复制代码
-- 所有员工数
SELECT COUNT(*) FROM employees;          -- 100 条

-- 有员工的部门数(去重后)
SELECT COUNT(DISTINCT dept_id) FROM employees;  -- 5 个

四、常见坑点与注意事项

坑 1:DISTINCT 不能部分去重

sql 复制代码
-- ❌ 语法错误:DISTINCT 只能放在 SELECT 后面第一个
SELECT emp_name, DISTINCT dept_id FROM employees;

-- ✅ 正确写法
SELECT DISTINCT dept_id, emp_name FROM employees;

坑 2:大结果集慎用 ORDER BY

sql 复制代码
-- 百万级数据全量排序非常慢
SELECT * FROM logs ORDER BY created_at DESC LIMIT 100;
-- ✅ 有 LIMIT 时数据库可能只排前 100 条(视优化器而定)

坑 3:字符串排序不是你以为的样子

sql 复制代码
-- 按数字字符串排序
SELECT id FROM tickets ORDER BY id;
-- 结果:1, 10, 100, 2, 20, 200 ...(字典序!)

-- 解决方案:类型转换
SELECT id FROM tickets ORDER BY CAST(id AS INTEGER);
-- 或补零:ORDER BY LPAD(id, 10, '0')

坑 4:DISTINCT 和 ORDER BY 的列必须匹配

sql 复制代码
-- ❌ 某些数据库报错
SELECT DISTINCT dept_id FROM employees ORDER BY salary;

-- ✅ 排序的列必须在 SELECT 中
SELECT DISTINCT dept_id, salary FROM employees ORDER BY salary;

🎯 今日总结

语法 要点
ORDER BY col ASC/DESC 默认 ASC,多列用逗号分隔
ORDER BY col DESC NULLS LAST PostgreSQL/Oracle 可用
LIMIT n OFFSET m MySQL/PostgreSQL 分页
OFFSET m FETCH NEXT n ONLY SQL 标准,SQL Server/PostgreSQL
DISTINCT 作用于所有选中列的组合
COUNT(DISTINCT col) 去重计数

一句话记住: 查结果想有序 → ORDER BY;查结果想去重 → DISTINCT;两样都想要 → 先 DISTINCTORDER BY,且排序列必须在 SELECT 中。

相关推荐
龙仔7254 小时前
SQL Server 批量多库只读账号一键脚本(带逐行注释完整脚本 + 分段逐句详细解释)
服务器·数据库·sql·sqlserver·dba
明天谭5 小时前
EzCloud自定义BI报表模块源码解析:动态SQL查询、可视化图表与多租户数据统计实现
数据库·sql·数据报表·bi可视化·ezcloud·java动态sql
爸爸61910 小时前
30 原始 SQL 查询与聚合统计:querySql 实战
数据库·sql·华为·harmonyos·鸿蒙系统
喜欢的名字被抢了21 小时前
Python实战:SQLAlchemy ORM与FastAPI项目集成
开发语言·python·sql·教程·fastapi
醉城夜风~1 天前
SQL DQL数据查询语言全套学习笔记(基础查询→执行顺序全解析)
笔记·sql·学习
Csvn1 天前
📊 SQL 入门 Day 1:SELECT & WHERE — 数据查询的基本功
后端·sql
苍狼唤1 天前
SQL+C# 增删改查(练习)
数据库·sql·c#
2301_800256111 天前
第七章 空间存储与索引 知识点梳理-2
数据库·sql·oracle
山峰哥2 天前
数据库工程与索引策略实战指南‌
服务器·数据库·sql·oracle·深度优先