如何从 table 中获取偶数或奇数记录?
how can I fetch even or odd records from a table?
我尝试使用以下两个查询来显示奇数或偶数记录。
select * from employee a
where 1 = mod(rownum,2);
select * from employee
where (rowid,1) in (select rowid, mod(rownum,2)
from employee);
第一个只显示员工的第一条记录table。而第二个查询完美无缺。拜托,谁能解释一下rownum是如何工作的??。
这是因为 rownum
的一个特点。它是一个 pseudo-column 应用于查询返回的结果集。 (这就是为什么 WHERE ROWNUM > 1
总是错误的。)
在这种情况下,使用 ROWNUM 会导致查询在 WHERE 子句 returns 为假时停止。所以这个 returns 没有行(因为 0 只对偶数行返回):
select * from employee a
where 0 = mod(rownum,2);
您的第二种方法有一个不在 WHERE 子句中使用 ROWNUM 的子查询,因此允许返回整个 table 以在外部查询中进行评估。
任何允许在不计算 ROWNUM 的情况下具体化整个结果集的方法都可以。这也将产生您想要的结果:
select * from
(select a.*, rownum as rn from employee a)
where mod(rn,2) = 1
/
正如@DavidAldridge 在他的评论中指出的那样,如果没有 ORDER BY 子句,结果集基本上是随机的。 ROWNUM 不能很好地与 ORDER BY 配合使用,因此要保证顺序,请改用分析函数 ROW_NUMBER()。
select * from
(select a.*
, row_number() over (order by a.emp_id) as rn
from employee a)
where mod(rn,2) = 0
/
" how bellow query fetches only first two records from table."
通过COUNT STOPKEY
操作的奇观。查询知道需要多少行;它 returns 行(并分配 ROWNUM 的值)直到达到该限制。
我们可以在 EXPLAIN PLAN 中看到这一点。没有过滤器:
SQL> explain plan for
2 select * from emp;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 111 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
12 rows selected.
SQL>
这是 where rownum <= 2
的计划。请注意所选行的差异:
SQL> explain plan for
2 select * from emp
3 where rownum <= 2;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1973284518
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 3 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=2)
Note
-----
- dynamic sampling used for this statement (level=2)
18 rows selected.
SQL>
您的问题是 rownum
的工作原理。
rownum
与 table 中的其他列不同;它是一个伪列。它仅针对最终结果集中的行递增。因此,获得第二行的著名示例是:
where rownum = 2
永远不会满足这个条件,因为rownum
第一行输出设置为1。所以,第一行得到过程。 rownum
是 1。它失败了 where
。处理第二行,rownum
还是1(因为结果集还是空),where
失败。等等。
最安全的解决方案是使用row_number()
:
select *
from (select a.*, row_number() over (order by rowid) as seqnum
from employee a
) a
where mod(seqnum, 2) = 1;
这符合您的预期。
老实说,以下内容也是如此:
select *
from (select a.*, rownum as seqnum
from employee a
) a
where mod(seqnum, 2) = 1;
子查询中没有过滤,行号按您预期的顺序分配。
我尝试使用以下两个查询来显示奇数或偶数记录。
select * from employee a
where 1 = mod(rownum,2);
select * from employee
where (rowid,1) in (select rowid, mod(rownum,2)
from employee);
第一个只显示员工的第一条记录table。而第二个查询完美无缺。拜托,谁能解释一下rownum是如何工作的??。
这是因为 rownum
的一个特点。它是一个 pseudo-column 应用于查询返回的结果集。 (这就是为什么 WHERE ROWNUM > 1
总是错误的。)
在这种情况下,使用 ROWNUM 会导致查询在 WHERE 子句 returns 为假时停止。所以这个 returns 没有行(因为 0 只对偶数行返回):
select * from employee a
where 0 = mod(rownum,2);
您的第二种方法有一个不在 WHERE 子句中使用 ROWNUM 的子查询,因此允许返回整个 table 以在外部查询中进行评估。
任何允许在不计算 ROWNUM 的情况下具体化整个结果集的方法都可以。这也将产生您想要的结果:
select * from
(select a.*, rownum as rn from employee a)
where mod(rn,2) = 1
/
正如@DavidAldridge 在他的评论中指出的那样,如果没有 ORDER BY 子句,结果集基本上是随机的。 ROWNUM 不能很好地与 ORDER BY 配合使用,因此要保证顺序,请改用分析函数 ROW_NUMBER()。
select * from
(select a.*
, row_number() over (order by a.emp_id) as rn
from employee a)
where mod(rn,2) = 0
/
" how bellow query fetches only first two records from table."
通过COUNT STOPKEY
操作的奇观。查询知道需要多少行;它 returns 行(并分配 ROWNUM 的值)直到达到该限制。
我们可以在 EXPLAIN PLAN 中看到这一点。没有过滤器:
SQL> explain plan for
2 select * from emp;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 111 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
12 rows selected.
SQL>
这是 where rownum <= 2
的计划。请注意所选行的差异:
SQL> explain plan for
2 select * from emp
3 where rownum <= 2;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1973284518
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 74 | 3 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| EMP | 3 | 111 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=2)
Note
-----
- dynamic sampling used for this statement (level=2)
18 rows selected.
SQL>
您的问题是 rownum
的工作原理。
rownum
与 table 中的其他列不同;它是一个伪列。它仅针对最终结果集中的行递增。因此,获得第二行的著名示例是:
where rownum = 2
永远不会满足这个条件,因为rownum
第一行输出设置为1。所以,第一行得到过程。 rownum
是 1。它失败了 where
。处理第二行,rownum
还是1(因为结果集还是空),where
失败。等等。
最安全的解决方案是使用row_number()
:
select *
from (select a.*, row_number() over (order by rowid) as seqnum
from employee a
) a
where mod(seqnum, 2) = 1;
这符合您的预期。
老实说,以下内容也是如此:
select *
from (select a.*, rownum as seqnum
from employee a
) a
where mod(seqnum, 2) = 1;
子查询中没有过滤,行号按您预期的顺序分配。