TOP 是一个在数据查询中非常常用的子句,用于限制返回结果集的行数。

TOP 的基本语法
TOP 子句的基本语法结构如下:
SELECT TOP (expression) [percent] column_list FROM table_name [WHERE conditions] [ORDER BY expression];
参数详解:
-
expression:- 这是一个整数,指定要返回的行数。
- 如果指定了
PERCENT,则expression是一个 0 到 100 之间的浮点数,表示百分比。 - 从 SQL Server 2012 (SQL Server 11.x) 开始,可以使用
WITH TIES选项,expression可以是一个非确定性值(使用NEWID())。
-
PERCENT:- 这是一个可选的关键字,如果指定,
TOP将返回结果集中前expression百分比的行,而不是固定的行数。 - 返回的行数会进行四舍五入。
TOP 10.5 PERCENT会返回总行数的 10.5%,然后四舍五入到最接近的整数。
- 这是一个可选的关键字,如果指定,
-
WITH TIES:
(图片来源网络,侵删)- 这是一个可选的关键字,必须与
ORDER BY子句一起使用。 - 当使用
WITH TIES时,TOP N中的最后一行在ORDER BY排序字段上的值与它后面的行的值相同,那么这些值相同的行也会被包含在结果中。 - 这可能导致返回的行数超过
N行。
- 这是一个可选的关键字,必须与
TOP 的使用场景和示例
假设我们有一个 Employees 表,包含以下数据:
CREATE TABLE Employees (
ID INT PRIMARY KEY,
Name NVARCHAR(50),
Salary DECIMAL(10, 2),
Department NVARCHAR(50)
);
INSERT INTO Employees (ID, Name, Salary, Department) VALUES
(1, '张三', 8000.00, '技术部'),
(2, '李四', 9500.00, '技术部'),
(3, '王五', 12000.00, '销售部'),
(4, '赵六', 15000.00, '销售部'),
(5, '钱七', 15000.00, '销售部'), -- 与赵六薪水相同
(6, '孙八', 11000.00, '市场部'),
(7, '周九', 8500.00, '技术部'),
(8, '吴十', 15000.00, '销售部'); -- 与赵六、钱七薪水相同
返回固定数量的行(最常用)
需求:查询薪水最高的前 3 名员工。
SELECT TOP 3
ID,
Name,
Salary
FROM
Employees
ORDER BY
Salary DESC;
结果: | ID | Name | Salary | |-----|------|---------| | 4 | 赵六 | 15000.00| | 5 | 钱七 | 15000.00| | 3 | 王五 | 12000.00|
解释:结果按薪水降序排列,只返回前 3 行。

返回固定百分比的数据
需求:查询薪水最高的前 25% 的员工。
SELECT TOP 25 PERCENT
ID,
Name,
Salary
FROM
Employees
ORDER BY
Salary DESC;
解释:总共有 8 名员工,25% of 8 = 2,所以理论上应返回 2 行。 结果: | ID | Name | Salary | |-----|------|---------| | 4 | 赵六 | 15000.00| | 5 | 钱七 | 15000.00|
使用 WITH TIES 处理并列情况
需求:查询薪水最高的前 2 名员工。
不使用 WITH TIES:
SELECT TOP 2
ID,
Name,
Salary
FROM
Employees
ORDER BY
Salary DESC;
结果: | ID | Name | Salary | |-----|------|---------| | 4 | 赵六 | 15000.00| | 5 | 钱七 | 15000.00|
问题:薪水第 3 高的“吴十”和“王五”虽然没在前 2 名,但他们的薪水(15000 和 12000)与第 2 名(15000)有并列的情况,如果业务逻辑要求“所有薪水前 N 名的员工”,这个结果就不完整。
使用 WITH TIES:
SELECT TOP 2 WITH TIES
ID,
Name,
Salary
FROM
Employees
ORDER BY
Salary DESC;
结果: | ID | Name | Salary | |-----|------|---------| | 4 | 赵六 | 15000.00| | 5 | 钱七 | 15000.00| | 8 | 吴十 | 15000.00| -- 因为薪水与第2名相同,被包含进来 | 3 | 王五 | 12000.00| -- 因为薪水与第2名不同,不被包含
解释:ORDER BY Salary DESC 后,前三行的薪水都是 15000。TOP 2 WITH TIES 会找到第 2 行(薪水15000),然后将所有薪水值等于 15000 的行都包含进来,直到遇到一个不同的值(12000),所以最终返回了 3 行。
在 UPDATE 和 DELETE 中使用 TOP
TOP 不仅可以用于 SELECT,还可以用于 UPDATE 和 DELETE 语句,这对于批量操作和性能优化非常有用。
示例:更新薪水最低的前 3 名员工的薪资
UPDATE TOP (3) Employees SET Salary = Salary * 1.1 ORDER BY Salary ASC; -- 必须使用 ORDER BY 来确定是“哪”前3名
解释:此语句会先按薪水升序排列,找出薪水最低的 3 名员工,然后将他们的薪水增加 10%。
示例:删除记录最旧的前 100 条日志
假设有一个 Logs 表,LogDate 字段记录了日志时间。
DELETE TOP (100) Logs ORDER BY LogDate ASC;
解释:删除 LogDate 最早的 100 条日志记录。
TOP 的替代方案(SQL Server 2000 及更早版本)
在 SQL Server 2000 中,TOP 语法不支持 WITH TIES 或 PERCENT,当时通常使用 SET ROWCOUNT 来实现类似功能。
SET ROWCOUNT 的用法:
-- 设置返回的行数为3 SET ROWCOUNT 3; SELECT * FROM Employees ORDER BY Salary DESC; -- 完成后务必将 ROWCOUNT 重置为 0,否则会影响后续所有语句 SET ROWCOUNT 0;
注意:SET ROWCOUNT 是一个会话级别的设置,会影响其后所有的 SELECT, UPDATE, DELETE 语句,使用时需要格外小心,并且操作完成后一定要重置,现代 SQL Server 编程中,强烈推荐使用 TOP 子句。
最佳实践和注意事项
-
始终配合
ORDER BY使用:当TOP用于SELECT语句时,如果不使用ORDER BY,返回的行是“不确定”的,只是数据库引擎认为“最快”返回的 N 行,这在不同版本、不同执行计划下可能会变化。为了结果的确定性,请务必使用ORDER BY。 -
WITH TIES需要明确的排序:WITH TIES的逻辑完全依赖于ORDER BY子句,确保你的排序字段能正确地定义“第一名”、“第二名”。 -
注意
PERCENT的四舍五入:TOP 10.5 PERCENT会进行四舍五入,这可能导致返回的行数比预期多一行或少一行。 -
在
UPDATE/DELETE中使用TOP:这是进行“批量操作”或“分批处理”的有效方法,可以避免一次性锁定过多资源或事务日志过大,从而提高性能和稳定性。 -
与
OFFSET-FETCH的比较:从 SQL Server 2012 开始,引入了更强大的分页语法OFFSET ... FETCH。TOP更侧重于“取前N”,而OFFSET-FETCH更侧重于“分页”。TOP N:SELECT TOP 10 ... ORDER BY ...- 分页 (跳过前10,取接下来的20):
SELECT ... ORDER BY ... OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY;
对于复杂的分页需求,
OFFSET-FETCH是更现代、更灵活的选择,但对于简单的“取前N”,TOP依然非常直观和高效。
| 功能 | 语法 | 说明 |
|---|---|---|
| 取固定行数 | SELECT TOP N ... |
返回结果集中的前 N 行。 |
| 取固定百分比 | SELECT TOP N PERCENT ... |
返回结果集中前 N% 的行。 |
| 处理并列 | SELECT TOP N WITH TIES ... |
必须配合 ORDER BY,如果第 N 行有并列,则返回所有并列行。 |
| 更新/删除 | UPDATE/DELETE TOP N ... |
用于批量更新或删除指定数量的记录,通常配合 ORDER BY 使用。 |
TOP 是 SQL Server 中一个基础但极其重要的工具,掌握它的各种用法可以让你在数据查询和数据操作中更加得心应手。
