大数据集分页

Pagination of large dataset

我有一个查询 returns 一个大型(10000 多行)数据集。我想按日期 desc 排序,并显示前 40 个结果。有没有办法 运行 这样的查询只检索这 40 个结果而不首先检索所有 10000 个结果?

我有这样的东西:

select rownum, date, * from table
order by date desc

这里选择了所有数据并按日期排序,但是rownum没有排序所以只选择前40个是没有用的。

ROW_NUMBER() over (ORDER BY date desc) AS rowNumber

^ 将按顺序显示行号,但我不能在 where 子句中使用它,因为它是一个 window 函数。我可以 运行 这个:

select * from (select ROW_NUMBER() over (ORDER BY date desc) AS rowNumber,
 rownum, * from table
order by date desc) where rowNumber between pageStart and pageEnd

但这是选择所有 10000 行。我怎样才能有效地做到这一点?

SELECT *
  FROM (SELECT *
          FROM table
         ORDER BY date DESC)
 WHERE rownum <= 40

将 return 按 date 排序的前 40 行。如果 date 上有一个索引可用于查找这些行,并且假设统计信息是最新的,Oracle 应该选择使用该索引来标识您想要的 40 行,然后执行 40 单行查找 table 以检索其余数据。如果你愿意,你可以在内部查询中抛出一个 /*+ first_rows(40) */ 提示,尽管那应该不会有任何影响。

有关分页查询和前 N 个查询的更一般性讨论,这里有一个很好的 discussion from Tom Kyte and a much longer AskTom discussion

您不需要 window 函数。见

http://www.techonthenet.com/oracle/questions/top_records.php

寻找问题的答案。

Oracle 12c 引入了一个 row limiting 子句:

SELECT *
FROM   table
ORDER BY "date" DESC
FETCH FIRST 40 ROWS ONLY;

在早期版本中你可以这样做:

SELECT *
FROM   ( SELECT *
         FROM   table
         ORDER BY "date" DESC )
WHERE  ROWNUM <= 40;

SELECT *
FROM   ( SELECT *,
                ROW_NUMBER() OVER ( ORDER BY "date" DESC ) AS RN
         FROM   table )
WHERE  RN <= 40;

SELECT *
FROM   TEST
WHERE  ROWID IN ( SELECT ROWID
                  FROM   ( SELECT "Date" FROM TEST ORDER BY "Date" DESC )
                  WHERE  ROWNUM <= 40 );

无论您做什么,数据库都需要查看 date 列中的所有值以找到前 40 个项目。