日期:2014-05-17  浏览次数:20836 次

关于ROWNUM和ORDER BY的问题
前两天同事发现网站上同一个商品在几页里都出现,然后查语句,发现有诡异的事情,原来以为可能是物化视图的关系,不过今天我测试了下,是和ORDER BY 里出现并列数据有关
先举例说明下
SQL code
SELECT a.*,rownum
  FROM (SELECT   good_id, good_nm, prc
            FROM tb_ag001
        ORDER BY prc) a

出来的结果


加了过滤
SQL code
SELECT *
  FROM (SELECT   good_id, good_nm, prc
            FROM tb_ag001
        ORDER BY prc)
 WHERE ROWNUM <9



另外种写法
SQL code
SELECT *
  FROM (SELECT   good_id, good_nm, prc
            FROM tb_ag001
        ORDER BY prc)
 WHERE ROWNUM <= 8



可以看到6-8项目不一样了,按道理rownum<=8和rownum<9结果是一样,但出现了不同,不过如果再包层,结果就一致了,并且是正确的
SQL code
SELECT *
  FROM (SELECT a.*, ROWNUM rn
          FROM (SELECT   good_id, good_nm, prc
                    FROM tb_ag001
                ORDER BY prc) a)
 WHERE rn < 9



SELECT *
  FROM (SELECT a.*, ROWNUM rn
  FROM (SELECT good_id, good_nm, prc
  FROM tb_ag001
  ORDER BY prc) a)
 WHERE rn <=8


------解决方案--------------------
帮顶
------解决方案--------------------
关注
UP
------解决方案--------------------
关注下
可能和子查询在内存中的排序有关吧
值相同时,排序不稳定。执行相同查询的时候,会从共享池中调用之前的结果
因为调用了相同的数据集
SELECT a.*, ROWNUM rn 
FROM (SELECT good_id, good_nm, prc 
FROM tb_ag001 
ORDER BY prc) a
因此rn<=8和rn<9是一样的

至于前面的写法,
 SELECT good_id, good_nm, prc
FROM tb_ag001
ORDER BY prc
order by会在内存中重新排序?因此2次排序结果不一定相同
这是我的猜测
------解决方案--------------------
SELECT *
FROM (SELECT good_id, good_nm, prc
FROM tb_ag001
ORDER BY prc)
 WHERE ROWNUM <9

这里的rownum与嵌套内层的rownum不相同,外层的rownum与嵌套内层的rownum没有任何关系
------解决方案--------------------
比如说下面这个语句
SELECT * 
FROM (SELECT good_id, good_nm, prc
FROM tb_ag001
ORDER BY prc) 
WHERE ROWNUM <9
红色部分查询出来的结果是经过ORDER BY 是有序的
所以结果就是从有序的结果集合中取出前9条

再看看另外一个
SELECT * 
FROM (SELECT a.*, ROWNUM rn 
FROM ([color=#FF0000]SELECT good_id, good_nm, prc 
FROM tb_ag001 
ORDER BY prc) a[/color]) 
WHERE rn < 9 
红色部分出来的结果是有序的 可是经过绿色的一个查询 结果还一定保持有序吗
如果已经不是有序的话 那么外层再选出的前9条可能也就不是刚才的前9条了
------解决方案--------------------

学习.. 先收藏下, 等会有空在研究下, 周一就是事多...
------解决方案--------------------
SELECT *
FROM (SELECT ROWNUM rn, good_id, good_nm, prc
FROM tb_ag001
ORDER BY prc) a
 WHERE rn < 9

这样就行
在内层查询中把数据按顺序附上了序号,在外层引用的时候可以直接当成实际存在的列来用
------解决方案--------------------
to hebo2005:

建议,你用分析函数,这样就排序就统一起来了。否则的话简单的oracle的rownum都需要嵌套3成,才可以排序的。
如下:
SQL code