2016-12-04 3 views
0

Я пытаюсь упростить ниже подзапросы, чтобы улучшить инструкцию select. У меня есть таблица с тремя основными столбцами как ID, GRAGE и AGE. Чтобы выбрать все записи, имеющие GRADE, такие же, как GRADE с максимальным ID Возможно, у кого-то есть лучший способ создания вложенных подзапросов, приветствуйте все ваши предложения?оптимизация запросов (вложенные подзапросы)

Примечание: Моя извинения за форматирование таблицы

ID GRADE  AGE 
10  A   30 
12  B   45 
13  A   15 
09  B   14 
20  A   12 
SELECT 
    * 
FROM 
    TABLE 
WHERE 
    GRADE = (
     SELECT 
      grade 
     FROM 
      TABLE 
     WHERE 
      id = (SELECT MAX(id) FROM TABLE) 
    ); 
+1

Если вы спросите для оптимизации perfromance этого запроса, а затем запустить пожалуйста 'EXPLAIN PLAN FOR your_query', то' SELECT * FROM таблицы (DBMS_XPLAN .Display) 'и, наконец, скопируйте результат последнего запроса ** в виде текста - а не растрового изображения ** и добавьте его в вопрос. – krokodilko

+0

@krokodilko И я бы добавил, что ответ может также зависеть от того, насколько велика таблица. –

ответ

1

Вы можете использовать КТР, чтобы сделать запрос легче читать:

WITH cte AS 
(
    SELECT GRADE, 
      ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID DESC) RowNum 
    FROM yourTable 
) 

SELECT * 
FROM yourTable 
WHERE GRADE = (SELECT t.GRADE FROM cte t WHERE t.RowNum = 1) 

Однако, я не имею проблема с вашим оригинальным подходом, потому что подзапросы не коррелируют ни с чем. Что я имею в виду, так это то, что

SELECT MAX(id) FROM yourTable 

должен эффективно выполняться только один раз, а затем сортироваться как константа. Аналогичным образом, запрос должен быть выполнен только один раз

. Это предполагает, что оптимизатор запросов достаточно умен, чтобы понять это, что, вероятно, есть.

+0

Спасибо, MAX vs PARTITION, который даст лучшую перформансу ?. – user881703

+0

И ваш подход, и мой, должны потребовать 2 полных сканирования таблицы. Пожалуйста, запустите 'EXPLAIN' в обоих запросах и убедитесь сами, что быстрее. –

0

Вы можете сделать следующее (не намного проще, хотя):

SELECT 
    * 
FROM 
    TABLE 
WHERE 
    GRADE IN (
     SELECT 
      first_value (GRADE) over (ORDER BY id DESC) 
     FROM 
      TABLE 
    )