我有一个返回大(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
^将按顺序显示rownumber,但我不能在where子句中使用它,因为它是一个窗口函数。我可以运行这个:
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行。我怎样才能有效地做到这一点?
答案 0 :(得分:5)
SELECT *
FROM (SELECT *
FROM table
ORDER BY date DESC)
WHERE rownum <= 40
将返回date
排序的前40行。如果date
上有一个可用于查找这些行的索引,并假设统计信息是最新的,那么Oracle应该选择使用该索引来识别所需的40行,然后执行40行单行查找表以检索其余数据。如果你想要,你可以在内部查询中抛出一个/*+ first_rows(40) */
提示,但不应该有任何影响。
有关分页查询和前N个查询的更一般性讨论,这里有一个很好的discussion from Tom Kyte和一个much longer AskTom discussion。
答案 1 :(得分:2)
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个第一项。
答案 2 :(得分:-1)