2015-07-09 5 views
1

У меня есть запрос, который возвращает большой набор данных (10000+ строк). Я хочу заказать по дате по убыванию и отобразить первые 40 результатов. Есть ли способ запустить такой запрос, который извлекает только эти 40 результатов без предварительного извлечения всего 10000?Разбиение большого набора данных

У меня есть что-то вроде этого:

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

Это выбирает все данные и распоряжения их по дате, но ROWNUM не в порядке, так что бесполезно для выбора только первый 40.

ROW_NUMBER() over (ORDER BY date desc) AS 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

какая база данных вы используете? – sstan

+0

Я использую Oracle –

+0

Является ли значение rowNumber между pageStart и pageEnd? – Luc

ответ

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

вернет первые 40 строк, упорядоченных по date. Если есть индекс на date, который может быть использован для поиска этих строк, и при условии, что статистика обновлена, Oracle должна выбрать этот индекс для определения 40 строк, которые вы хотите, а затем выполнить 40 однострочных запросов по таблице для извлечения остальных данных. Вы могли бы набросать подсказку /*+ first_rows(40) */ во внутренний запрос, если хотите, хотя это не должно иметь никакого эффекта.

Для более общей дискуссии о запросах на разбиение на страницы и в верхних N-запросах, вот хороший discussion from Tom Kyte и much longer AskTom discussion.

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 первых элементов.