записи, например:
id__name
2__Слава
5__Артем
7__Лера
и есть вторая таблица:
user_id___description
2_________учится во 2-м классе
5_________закончио школу
как построить запрос, чтобы найти id из первой таблицы, id которых нет во второй? в моём примере нет id 7.
я думал inner join'ом сделать, но моя задумка не сработала.
leftjoin
"Которых нет" → "NOT EXISTS"
уже пытаюсь с ней магию сделать)
в чем я ошибаюсь в запросе? 🤔 SELECT * FROM mapping WHERE NOT EXISTS (SELECT * FROM order2product INNER JOIN mapping m on order2product.core_id = m.sync_id)
Эээ... во всём (что это вообще должно значить, логически)?! Вам нужно написать запрос "выбрать поле id каждой записи из первой таблицы, для которой во второй таблице не существует записи с таким id". Вот и пишите: SELECT id -- выбрать поле id каждой записи FROM первая_таблица -- из первой таблицы WHERE NOT EXISTS ( -- для которой не существует записи SELECT 1 FROM вторая_таблица -- во второй таблице WHERE вторая_таблица.id_первая_таблица = первая_таблица.id -- с таким id );
Вопрос к этому оффтоп: В MSSQL гораздо более эффективно работал следующий запрос - SELECT id FROM первая_таблица LEFT JOIN вторая_таблица ON условие WHERE поле_из_второй_таблицы IS NULL В PG иначе?
спасибо большое за развернутый ответ! очень благодарен
почему-то Ораклом запахло. Знакомый Оракловод также пишет :)
Во-первых — нет, в MS SQL уже лет 20 как это неправда (но преданья старины упорно повторяют... и уродуют код из-за, фактически, веры в "миф"). ;) Во-вторых, насколько я помню, в PostgreSQL планы (всегда?) получаются идентичные.
ну по поводу уродования - субъективно. По мне дак чем короче код, тем лучше. По поводу работы - в 2005 точно работало так как я пислал. И на 2014 работало с той же производительносью, так как не перепысывали. По поводу планов - есть опции которые способны на это повлиять и статистика, так что слово «всегда» наверное не применимо. На сферическом коне, который не работет и не делает вакуум - наверное идентично.
> ну по поводу уродования - субъективно. Ну вот я там выше приводил пример, как запрос практически 1:1 соответствует его записи на естественном языке. А с LEFT JOIN можете такое же показать? > По поводу работы - в 2005 точно работало так как я пислал. Нет, не работало, и да, точно. Я бы поспорил, но a) это offtopic и б) сейчас 2005 пойди найди. Впрочем, можете погуглить... > И на 2014 работало с той же производительносью, так как не перепысывали. Если "с той же", это одно дело. А вот неверное утверждение, что "LEFT JOIN ... WHERE t2.id IS NULL" лучше — совсем другое. ;) > По поводу планов - есть опции которые способны на это повлиять и статистика Может быть. Но есть такая вещь, как трансформации текста запроса в то, что может реально выполняться (paths, plans и их nodes). И такой LEFT JOIN вполне может преобразовываться в anti join ещё до оценок, и на том возможность чего-то влиять на планы заканчивается — но это нужно смотреть в исходниках.
И я таки заглянул в исходники — слово "всегда" практически применимо, на первый взгляд ( https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/optimizer/prep/prepjointree.c;h=14521728c633bf86c16871c9eb77c95a8f8732a0;hb=HEAD#l2542 ): Another transformation we apply here is to recognize cases like SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL; If the join clause is strict for b.y, then only null-extended rows could pass the upper WHERE, and we can conclude that what the query is really specifying is an anti-semijoin. We change the join type from JOIN_LEFT to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be removed to prevent bogus selectivity calculations ... И https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/optimizer/plan/subselect.c;h=fcce81926b7d6948a3bd12ae592a946abc4ff7bb;hb=HEAD#l1376 : convert_EXISTS_sublink_to_join: try to convert an EXISTS SubLink to a join ... we also support the case where the caller has found NOT EXISTS,
ну судя по всему да, и там и там должен на выходе получиться JOIN_ANTI и код должен работать идентично
Да, похоже на то. Т.е. это ещё до оценок происходит, поэтому статистика и т.п. на это не влияет.
ну видимо потому что статистика уже потом нужна чтобы понять использовать индексы или обход делать, а базовая операция от этого отличаться не будет
Обсуждают сегодня