Oracle SELECT TOP 10 записей

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

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

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+ записей).

Комментарии к вопросу (2)
Решение

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


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 
Комментарии (4)

Если вы используете Oracle 12С, используйте:

принести следующий Н строк только

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
FETCH NEXT 10 ROWS ONLY

Подробнее: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html

Комментарии (5)

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

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-дерева.

Комментарии (0)

попробовать

SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
Комментарии (1)

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


 select * from 
     (select empno,
             ename,
             sal,
             row_number() over(order by sal desc nulls last) rnm
    from emp) 
 where rnm
Комментарии (0)