在甲骨文的rownum之谜

时间:2015-10-05 23:22:45

标签: oracle oracle11g

我正在努力获取基于rownum的数据。当我执行以下查询以获得基于rownum 1 to 4的结果时,它工作正常。

  SELECT ROWNUM TOTAL,MI.* FROM (SELECT USER_ID,CUSTOMER_NAME FROM ELEC_AUTO_MERC 
  ORDER BY CREATION_DATE DESC ) MI WHERE ROWNUM BETWEEN 1 AND 4;

但是当我执行相同的查询以从rownum 2 to 4获取结果时,它不起作用,它不会返回任何内容。

  SELECT ROWNUM TOTAL,MI.* FROM (SELECT USER_ID,CUSTOMER_NAME FROM ELEC_AUTO_MERC 
  ORDER BY CREATION_DATE DESC ) MI WHERE ROWNUM BETWEEN 2 AND 4;

作为一种解决方法,当我再使用一个SELECT语句时,它工作正常,但我不认为仅对rownum多次使用SELECT是好方法。

SELECT * FROM (SELECT ROWNUM TOTAL,MI.* FROM (SELECT USER_ID,CUSTOMER_NAME FROM ELEC_AUTO_MERC 
  ORDER BY CREATION_DATE DESC ) MI) WHERE TOTAL BETWEEN 2 AND 4;

您可以帮我创建优化查询吗?

1 个答案:

答案 0 :(得分:3)

ROWNUM很奇怪,它可以作为查询条件的一部分进行评估 - 但如果该行无法通过该过滤器,则分配的ROWNUM值可用于再次用于下一行。

这样做的一个重要影响是,如果您使用排除ROWNUM值为1的任何条件,您将永远不会得到匹配。针对此条件进行测试的第一行将是第1行;但那么它将无法通过测试,因此下一行将被视为第1行;等等。

所以你的条件ROWNUM BETWEEN 2 AND 4永远不会成真。

您找到的解决方法是传统的解决方法。另一种方法是使用分析函数对行进行排名,然后对排名进行过滤,例如:

SELECT MI.* FROM (
  SELECT USER_ID,CUSTOMER_NAME, RANK() OVER (ORDER BY CREATION_DATE DESC) AS the_rank
  FROM ELEC_AUTO_MERC 
  ) MI
WHERE the_rank BETWEEN 2 AND 4;

几个分析函数 - RANK,DENSE_RANK和ROW_NUMBER - 可用于此目的,并且会产生稍微不同的结果,尤其是在存在关联的情况下。查看文档。