【问题标题】:Get range of records from SQL query Oracle从 SQL 查询 Oracle 获取记录范围
【发布时间】:2012-04-22 21:44:48
【问题描述】:

我想用这个 SQL 查询只获取 8 到 10 之间的记录:

select *
from(
SELECT a.*,rownum rn 
FROM ACTIVESESSIONSLOG  a
ORDER BY USERID ASC)
WHERE rn  >= 8 and rn <= 10

当我将这个 SQL 查询实现到分页中时,无论我配置了多少行显示到页面中,我每次都会在第二页上获得 1 行。这个 SQL 查询有效吗?

这是表结构:

-- TABLE ACTIVESESSIONSLOG

CREATE TABLE ACTIVESESSIONSLOG(
  ASESSIONID VARCHAR2(30 ) NOT NULL,
  USERID VARCHAR2(30 ),
  ACTIVITYSTART TIMESTAMP(6),
  ACTIVITYEND TIMESTAMP(6),
  ACTIVITY CLOB
)
/

最好的祝福

【问题讨论】:

  • 您在查找第二页时是否更改了内部查询?
  • 查询看起来正确,但我不明白问题到底是什么。
  • 如果没有 WHERE 子句,究竟返回多少行?第 2 页执行的查询到底是什么? (不是您所知道的应该,而是您在调试代码时发现了什么?)
  • 代码对我来说也很好用 (sqlfiddle.com/#!4/7069a/1)。

标签: sql oracle oracle10g oracle11g


【解决方案1】:

rownumORDER BY 之前应用,因此您的查询几乎肯定没有达到您的预期。您的查询本质上是要求任意 3 行,而 ORDER BY 没有做任何有用的事情。

您可以改用解析函数row_number,即

SELECT *
  FROM (SELECT a.*,
               row_number() over (order by userid asc) rn
          FROM activeSessionsLog a)
 WHERE rn BETWEEN 8 AND 10

这将翻阅结果

SQL> ed
Wrote file afiedt.buf

  1  select empno, ename, job
  2    from (select e.*,
  3                 row_number() over (order by empno) rn
  4            from emp e)
  5*  where rn between 1 and 3
SQL> /

     EMPNO ENAME      JOB
---------- ---------- ---------
      7369 SMITH      CLERK
      7499 ALLEN      SALESMAN
      7521 WARD       SALESMAN

SQL> ed
Wrote file afiedt.buf

  1  select empno, ename, job
  2    from (select e.*,
  3                 row_number() over (order by empno) rn
  4            from emp e)
  5*  where rn between 4 and 8
SQL> /

     EMPNO ENAME      JOB
---------- ---------- ---------
      7566 JONES      MANAGER
      7654 MARTIN     SALESMAN
      7698 BLAKE      MANAGER
      7782 CLARK      MANAGER
      7788 SCOTT      ANALYST

SQL> ed
Wrote file afiedt.buf

  1  select empno, ename, job
  2    from (select e.*,
  3                 row_number() over (order by empno) rn
  4            from emp e)
  5*  where rn between 9 and 11
SQL> /

     EMPNO ENAME      JOB
---------- ---------- ---------
      7839 KING       PRESIDENT
      7844 TURNER     SALESMAN
      7876 ADAMS      CLERK

但是,执行类似这样的操作可能更有效,Oracle 可以使用内部的rownum &lt;= 10 谓词知道一旦识别出前 10 行就可以停止对数据进行排序。

SELECT c.*
  FROM (SELECT b.*, rownum rn
          FROM (SELECT a.*
                  FROM activeSessionsLog a
                 ORDER BY userid asc) b
         WHERE rownum <= 10) c
 WHERE rn >= 8

【讨论】:

    【解决方案2】:

    从 Oracle 12c 开始,您现在可以使用 offset/fetch 子句了。

    您现在可以编写如下查询:

    SELECT *
    FROM user_objects
    ORDER object_name
    OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
    

    请查看此new feature 并考虑执行计划中的改进。

    【讨论】:

      猜你喜欢
      • 2019-03-18
      • 2022-12-05
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 2020-07-28
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多