简体   繁体   English

Oracle Rownum SQL

[英]Oracle Rownum SQL

What are the differences (advantages and disadvantages) between these two coding techniques?这两种编码技术之间有什么区别(优点和缺点)?

select * from (
    select rownum rnun, * from table where rownum < x
) where rnum > y


select * from (
    select * from table
) where rownum < x and x > y

The two queries return different rows.这两个查询返回不同的行。

Neither query is deterministic.这两个查询都不是确定性的。 So neither query should ever be used in a real system.因此,任何查询都不应该在实际系统中使用。

The first query appears to be at least an attempt to generate a window of rows (rows between x and y).第一个查询似乎至少是尝试生成行(x 和 y 之间的行)的 window。 Since there is no ORDER BY, however, the order of rows is not deterministic and the window probably doesn't do what you want.但是,由于没有 ORDER BY,因此行的顺序不是确定性的,并且 window 可能无法满足您的要求。

The second query returns an arbitrary x rows of data (assuming x > y).第二个查询返回任意 x 行数据(假设 x > y)。 Otherwise it returns 0 rows (if y >= x).否则返回 0 行(如果 y >= x)。 If you're trying to build some sort of windowing query, this isn't it.如果您正在尝试构建某种窗口查询,则不是这样。

If you want a windowing query that works, you'd want something like如果你想要一个有效的窗口查询,你会想要类似的东西

SELECT *
  FROM (SELECT a.*,
               row_number() over (order by something) rnum
          FROM table_name)
 WHERE rnum BETWEEN x AND y

If you wanted to use ROWNUM, you'd need something like如果你想使用 ROWNUM,你需要类似的东西

SELECT *
  FROM (SELECT a.*,
               rownum rnum
          FROM( SELECT b.*
                  FROM table_name
                 ORDER BY something) a)
 WHERE rownum < y
   AND rnum > x

But this tends to be less efficient than the analytic query approach.但这往往比分析查询方法效率低。

Besides the absence of the “order by” clause….. May be the question is about Oracle STOPKEY feature?除了没有“order by”条款之外……问题可能是关于 Oracle STOPKEY 功能? In case of “paging” queries Oracle can use a STOPKEY feature to limit the number of rows in the subquery, this can lead to some performance gain.在“分页”查询的情况下,Oracle 可以使用 STOPKEY 功能来限制子查询中的行数,这可能会带来一些性能提升。

Look at this query:看看这个查询:

select *
  from (select a.*,
               row_number() over (order by sname) rnum
          from t_patient_card a)
 where rnum between 1 and 100           

                                                        Cost    Cardinality

SELECT STATEMENT, GOAL = FIRST_ROWS                     313272  3571266
 VIEW        HOSPITAL2$                                 313272  3571266
  SORT ORDER BY                                         313272  3571266
   COUNT
  TABLE ACCESS FULL    HOSPITAL2$    T_PATIENT_CARD     38883   3571266

Oracle fetched all the rows before is return only 100 of them Oracle 之前获取的所有行只返回其中的 100 个

Let's rewrite the query like this:让我们像这样重写查询:

select *
  from (
  select rownum as rn,tt.*  from  
  (
   select  t.* from t_patient_card t order by  t.sname
  )tt where rownum<100       
    ) 
 WHERE rn >1

In this case we user rownum<100 in the subquery to inform the optimizer that we want to get less the 100 rows.在这种情况下,我们在子查询中使用 rownum<100 来通知优化器我们想要减少 100 行。

                                                        Cost    Cardinality
SELECT STATEMENT, GOAL = ALL_ROWS                       313272  99
 VIEW    HOSPITAL2$                                     313272  99
  COUNT STOPKEY
   VIEW    HOSPITAL2$                                   313272  3571266
    SORT ORDER BY STOPKEY                               313272  3571266
  TABLE ACCESS FULL    HOSPITAL2$    T_PATIENT_CARD     38883   3571266

You can see the “count stopkey” and cardinality is only 99 after this step.In my database the second query executes one second faster then the first one.在这一步之后,您可以看到“count stopkey”和基数只有 99。在我的数据库中,第二个查询的执行速度比第一个查询快一秒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM