Unstupidify этот запрос с помощью объединений - PullRequest
1 голос
/ 25 января 2012

У меня есть этот запрос, который работает:

select name, location_id from all_names
where location_id in (1,2,3)
and name in(select name from my_names) 
and (name, location_id) not in (select name,location_id from my_names);

Цель этого запроса - найти все кортежи name, location_id в all_names, которых нет в my_names, если эти имена ARE в my_names.

Будучи относительно любителем SQL, я попытался провести некоторое исследование, чтобы исправить этот запрос, но он не совсем работает. В основном я пытался использовать кортежи внешнего соединения (name, location_id) из my_name и all_names и идентифицировать те строки, которые возвращают нули, потому что это будут строки, которые не имеют соответствия.

select data.name, data.location_id
from
(select all.name, all.location_id, my.name, my.location_id l_id
from (select name, location_id
from all_names
where location_id in (1,2,3)
)all,
(select name, location_id
from my_names
)my
where all.name = my.name(+)
and all.location_id = my.location_id(+)) data
where data.l_id is null
and data.name is null;

Это работает всякий раз, когда я добавляю "где data.name = 'SomeSpecificName'", но когда я просто запускаю его без него, он возвращает слишком много строк. Можете ли вы помочь мне понять, где я иду не так?

Ответы [ 4 ]

2 голосов
/ 25 января 2012

Я думаю, что ваш текущий запрос в порядке.

IN и NOT IN более эффективны, чем вы думаете.Составьте план запроса и сравните его с ответом RedFilter.

1 голос
/ 25 января 2012
select a.name, a.location_id 
from all_names a
inner join my_names m on a.name = m.name
left outer join my_names m2 on a.name = m2.name and a.location_id = m2.location_id
where a.location_id in (1,2,3)
    and m2.name is null
0 голосов
/ 26 января 2012

Не уверен, как выглядит план запроса, но вы можете попробовать:

select a.name, a.location_id
from all_names a, my_names m
where a.location_id in (1,2,3)
and a.name = m.name
minus
select name, location_id
from my_names

Это довольно четкий способ выразить свое намерение и возможность использовать часто забываемый оператор minus.

0 голосов
/ 25 января 2012

Или

SELECT
    name,
    location_id
FROM
    all_names a
WHERE
    location_id IN (1,2,3) AND
    name IN (SELECT * FROM my_names) AND
    NOT EXISTS (SELECT * 
                FROM my_names m 
                WHERE m.location_id=a.location_id AND m.name=a.name)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...