SQL 跳过n行记录,你想用一个查询来隔行返回 EMP
表中的记录;你希望获得第一个员工、第三个员工,等等。例如,从下面的结果集。
SQL 跳过n行记录 问题描述
你想用一个查询来隔行返回 EMP
表中的记录;你希望获得第一个员工、第三个员工,等等。例如,从下面的结果集:
ENAME
--------
ADAMS
ALLEN
BLAKE
CLARK
FORD
JAMES
JONES
KING
MARTIN
MILLER
SCOTT
SMITH
TURNER
WARD
你希望返回的是:
ENAME
----------
ADAMS
BLAKE
FORD
JONES
MARTIN
SCOTT
TURNER
SQL 跳过n行记录 解决方案
为了从一个结果集中跳过第 2 行、第 4 行或第 n 行,我们必须对结果集先排序,否则就没有所谓的“第一个”“下一个”“第二个”或者“第四个”等概念。
DB2、Oracle 和 SQL Server
使用窗口函数 ROW_NUMBER OVER
为每一行分配一个序号,这样就可以借助模函数跳过我们不想要的行了。DB2 和 Oracle 的模函数是 MOD
。SQL Server 则使用 %
操作符。下面的例子使用 MOD
跳过编号为偶数的行。
1 select ename
2 from (
3 select row_number() over (order by ename) rn,
4 ename
5 from emp
6 ) x
7 where mod(rn,2) = 1
MySQL 和 PostgreSQL
这两种数据库不提供支持排序或为每一行数据编排序号的内置函数,因而需要使用标量子查询来模拟实现类似功能(本例中根据员工名字排序),然后使用模函数跳过不需要的行。
1 select x.ename
2 from (
3 select a.ename,
4 (select count(*)
5 from emp b
6 where b.ename <= a.ename) as rn
7 from emp a
8 )x
9 where mod(x.rn,2) = 1
SQL 跳过n行记录 扩展知识
DB2、Oracle 和 SQL Server
在内嵌视图 X
里调用窗口函数 ROW_NUMBER OVER
将会为每一行分配一个序号(没有附加任何条件,也不去除重复的姓名),结果显示如下。
select row_number() over (order by ename) rn, ename
from emp
RN ENAME
-- --------
1 ADAMS
2 ALLEN
3 BLAKE
4 CLARK
5 FORD
6 JAMES
7 JONES
8 KING
9 MARTIN
10 MILLER
11 SCOTT
12 SMITH
13 TURNER
14 WARD
最后,只需调用模函数跳过不需要的行即可。
MySQL 和 PostgreSQL
因为没有内置函数帮助我们为每一行编号,我们改用标量子查询为员工的名字编号。内嵌视图 X
实现了为每个名字编号,结果如下所示。
select a.ename,
(select count(*)
from emp b
where b.ename <= a.ename) as rn
from emp a
ENAME RN
---------- ----------
ADAMS 1
ALLEN 2
BLAKE 3
CLARK 4
FORD 5
JAMES 6
JONES 7
KING 8
MARTIN 9
MILLER 10
SCOTT 11
SMITH 12
TURNER 13
WARD 14
最后,针对产生的行编号调用模函数来跳过不需要的行。