Записи TOP 10 ВЫБОРА Oracle

У меня есть большая проблема с SQL-оператором в Oracle. Я хочу выбрать Записи TOP 10, заказанные STORAGE_DB, которые не находятся в списке от другого избранного оператора.

Этот хорошо работает для всех записей:

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
      STORAGE_GB IS NOT NULL AND 
        APP_ID NOT IN (SELECT APP_ID
                       FROM HISTORY
                        WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

Но когда я добавляю

AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC

Я получаю некоторые "случайные" Записи. Я думаю, потому что предел берет на месте перед порядком.

У кого-то есть хорошее решение? Другая проблема: Этот запрос является действительно медленным (10k + записи)

123
задан Ryan Weaver 9 February 2017 в 16:41
поделиться

3 ответа

Вам нужно поместить текущий запрос в подзапрос, как показано ниже:

SELECT * FROM (
  SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC )
WHERE ROWNUM <= 10

Oracle применяет rownum к результату после его возврата.
Вам необходимо отфильтровать результат после того, как он был возвращен, поэтому требуется подзапрос. Вы также можете использовать функцию RANK () для получения результатов Top-N.

Для повышения производительности попробуйте использовать NOT EXISTS вместо NOT IN . Подробнее см. , .

177
ответ дан 24 November 2019 в 01:14
поделиться

Что касается плохой производительности, то это могло быть множество вещей, и это действительно должен быть отдельный вопрос. Однако есть одна очевидная вещь, которая может быть проблемой:

WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

Если HISTORY_DATE действительно является столбцом даты и если у него есть индекс, то эта перезапись будет работать лучше:

WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')  

Это связано с тем, что преобразование типа данных запрещает использование Индекс B-Tree.

23
ответ дан 24 November 2019 в 01:14
поделиться

Вы получаете явно случайный набор, потому что ROWNUM применяется перед ORDER BY. Итак, ваш запрос берет первые десять строк и сортирует их.0 Чтобы выбрать десять самых высоких зарплат, вы должны использовать аналитическую функцию в подзапросе, а затем отфильтровать это:

 select * from 
     (select empno,
             ename,
             sal,
             row_number() over(order by sal desc nulls last) rnm
    from emp) 
 where rnm<=10
10
ответ дан 24 November 2019 в 01:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: