2013-05-30 3 views
0

Я почти новичок в запросах базы данных. Однако я понимаю, почему и как коррелированные подзапросы стоят дорого и лучше всего избегают. Учитывая следующий простой пример - кто-то может помочь замена с объединением, чтобы помочь понять, как он забивает лучше:Присоединяйтесь к подзапросу

SQL> select 
    2 book_key, 
    3 store_key, 
    4 quantity 
    5 from 
    6 sales s 
    7 where 
    8 quantity < (select max(quantity) 
    9     from sales 
10     where book_key = s.book_key); 

Помимо присоединиться, что другие опции мы должны избежать подзапрос.

+0

Итак, вы хотите решение, которое не использует JOIN? – RobB

+0

@RobB Я думаю, да – Luv

+0

@ Я не мог подтвердить, потому что ваш вопрос противоречив, в частности: «Помимо объединения, какой другой вариант нам нужно избежать подзапроса». – RobB

ответ

0

В этом случае, она должна быть лучше использовать оконную функцию на одном доступе к столу - вот так:

with s as 
(select book_key, 
     store_key, 
     quantity, 
     max(quantity) over (partition by book_key) mq 
from sales) 
select book_key, store_key, quantity 
from s 
where quantity < s.mq 
+0

Я думаю, что это дороже предыдущего запроса – Luv

+0

@ Luv: Этого не должно быть; для этого подхода требуется только один доступ к таблице, тогда как исходный запрос имеет один доступ к таблице в основном запросе, плюс один доступ для каждой строки основной таблицы запросов в подзапросе. –

-1

Помимо присоединиться, что других опциями мы должны избегайте подзапроса.

Вы можете использовать что-то вроде этого:

SELECT select max(quantity) 
INTO @myvar 
from sales 
where book_key = s.book_key 

select book_key,store_key,quantity 
from sales s 
where quantity < @myvar 
0

Использование Common Table Expressions (КТР) позволит выполнить один основной ЗЕЬЕСТ и сохранить результат во временном наборе результатов. Затем данные могут быть самоназванными и доступными несколько раз, не требуя повторного выполнения первоначальной инструкции SELECT и не потребуют дорогостоящих JOIN. Это решение также использует ROW_NUMBER() и предложение OVER для номера соответствующих BOOK_KEYs в порядке убывания, исходя из количества. Затем вы включаете только записи, количество которых меньше максимального количества для каждого BOOK_KEY.

with CTE as 
(
    select 
    book_key, 
    store_key, 
    quantity, 
    row_number() over(partition by book_key order by quantity desc) rn 
    from sales 
) 
select 
    book_key, 
    store_key, 
    quantity 
from CTE where rn > 1; 

Рабочая Демо: http://sqlfiddle.com/#!3/f0051/1

+0

Возможно, rank(), а не row_number() - что, если в нескольких магазинах было одинаковое (максимальное) количество книг? –

Смежные вопросы