Oracle中的NTH行查询不符合预期

时间:2016-11-02 20:01:59

标签: sql oracle

鉴于;

CREATE TABLE T1 (ID INTEGER, DESCRIPTION VARCHAR2(20));
INSERT INTO T1 VALUES (1,'ONE');
INSERT INTO T1 VALUES (2,'TWO');
INSERT INTO T1 VALUES (3,'THREE');
INSERT INTO T1 VALUES (4,'FOUR');
INSERT INTO T1 VALUES (5,'FIVE');
COMMIT;

为什么;

SELECT * FROM 
( SELECT ROWNUM, ID, DESCRIPTION
  FROM T1)
WHERE MOD(ROWNUM,1)=0;  

返回

ROWNUM                                     ID DESCRIPTION        
------ -------------------------------------- --------------------
     1                                      1 ONE                  
     2                                      2 TWO                  
     3                                      3 THREE                
     4                                      4 FOUR                 
     5                                      5 FIVE 

鉴于;

SELECT * FROM 
( SELECT ROWNUM, ID, DESCRIPTION
  FROM T1)
WHERE MOD(ROWNUM,2)=0; 

返回零行???

困惑,预计ROWNUM =(2,4)将被退回......

3 个答案:

答案 0 :(得分:1)

SELECT B.* FROM 
( SELECT ROWNUM a, ID, DESCRIPTION
  FROM T1) B
WHERE MOD(A,2)=0; 

原因:您的方法涉及两次运行rownum。你不需要;你真的不想。根据操作顺序,where子句将在外部select之前执行;这意味着select尚未确定每行的值,并且行数尚未知晓。

其他:

我建议在内联视图中添加一个订单,以便rownumber按照预期的特定顺序而不是引擎派生的顺序。

答案 1 :(得分:1)

ROWNUM 2 操作。
第1个ROWNUM生成数字1到5 第二个ROWNUM不生成任何内容,因为对于ROWNUM值为1的行,但由于MOD(1,2)=0为false,因此未输出记录且ROWNUM没有递增,一次又一次地使条件失败。

此查询使用别名,准确返回您所期望的内容:

SELECT * FROM 
( SELECT ROWNUM as rn, ID, DESCRIPTION
  FROM T1)
WHERE MOD(rn,2)=0; 

答案 2 :(得分:0)

关于Oracle中ROWNUM伪列的一些事实:

  • 分配给每一行的ROWNUM由Oracle从数据库中检索行的顺序决定。
  • 返回行的顺序是不确定的,因此运行一次可能会返回一个排序中的行,如果基表已重新组织,则第二次可能会有不同的顺序,或者Oracle使用不同的查询计划。
  • ROWNUM分配给行的顺序不一定与order by子句的顺序相关(order by子句可能会影响ROWNUM顺序,因为它可能会导致不同的查询计划使用,但ROWNUM bers不太可能与排序顺序匹配。)
  • 在记录被ROWNUM子句过滤后,
  • WHERE bers被分配,因此如果您过滤掉ROWNUM 1,则永远不会返回任何记录。
  • 过滤返回别名ROWNUM列的子查询是有效的,因为在外部查询过滤行之前,整个子查询将返回到外部查询,但ROWNUM仍将具有非确定性顺序

要以确定的方式成功返回前N行或第N行查询,您需要以确定的方式分配行号。一种方法是使用`ROW_NUMBER'子查询中的分析函数:

select * from
 (select ROW_NUMBER() over (order by ID) rn
       , ID
       , DESCRIPTION
    from T1)
 where rn <= 4 -- Top N

 where rn = 4 -- 1st Nth row

甚至

 WHERE MOD(rn,2)=0 -- every Nth row

在任何一种情况下,ORDER BY分析函数中的ROW_NUMBER子句都需要匹配数据的粒度,否则排序中的关系将再次是非确定性的,很可能与当前{{1}匹配订购。