NOT EXISTS в Postgresql
Кто-нибудь знает, как выполнить такой запрос в Postgresql?
SELECT *
FROM tabA
WHERE NOT EXISTS (
SELECT *
FROM tabB
WHERE tabB.id = tabA.id
)
Когда я выполняю такой запрос, postgresql жалуется на "ERROR: Greenplum Database does not yet support that query
."
EDIT: И как насчет этого:
SELECT *
FROM tabA
WHERE NOT EXISTS (
SELECT *
FROM tabB WHERE tabB.id = tabA.id AND tabB.id2 = tabA.id2
)
РЕДАКТИРОВАТЬ:
Я тестировал в postgresql 8.2.15 для 4 ответов, предоставленных @ypercube. Выводы:
1) Первое не работает в этой версии postgresql, как я сказал выше в вопросе. Сообщение об ошибке также можно найти там.
2) Для остальных трех ответов скорость выполнения: (3) LEFT JOIN > (4) ЗА ИСКЛЮЧЕНИЕМ → (2) NOT IN.
В частности, для запросов, имеющих один и тот же синтаксис, (3) LEFT JOIN занимает около 5580 мс, (4) EXCEPT занимает около 13502 мс, а (2) NOT IN занимает более 100000 (на самом деле я не ожидал,).
Есть ли какие-то особые причины для того, чтобы предложение NOT IN было настолько медленным?
Cheng
Ответы
Ответ 1
Существует 3 (основных) способа выполнения такого рода запросов:
Вы обнаружили, что первый способ работает в Greenplum. @Marco и @juergen предоставили второй путь. Здесь третий, он может обойти ограничения Greenplum:
SELECT tabA.*
FROM
tabA
LEFT JOIN
tabB
ON tabB.id = tabA.id
AND tabB.id2 = tabA.id2
WHERE tabB.id IS NULL ;
Этот (4-й путь) также работает в Postgres (который поддерживает оператор EXCEPT
):
SELECT a.*
FROM a
WHERE id IN
( SELECT id
FROM a
EXCEPT
SELECT id
FROM b
) ;
Протестировано в SQL-Fiddle (все 4 работы в Postgres).
Ответ 2
Часть ошибки, которую вы оставили вне, могла бы указать вам в правильном направлении. Я думаю, он сказал: "ДЕТАЛИ: запрос содержит коррелированный подзапрос". Поэтому вы должны переписать их с помощью соединений или некоррелированных подзапросов.
SELECT * FROM tabA WHERE id NOT IN (SELECT id FROM tabB);
Что касается второго запроса, попробуйте
SELECT * FROM tabA WHERE (id, id2) NOT IN (SELECT id, id2 FROM tabB);
Ответ 3
SELECT * FROM tabA
WHERE id not in (SELECT id FROM tabB)