LINUX.ORG.RU

Как найти в таблице A записи, которых нет в B

 


2

1

Чего-то затупил. Есть таблица А, есть таблица B. Надо показать все записи с полем A.column1 которых нет в B. Не которые есть, а которых нет. То есть этакий not JOIN что ли.

Просто JOIN разумеется возможен по полю, то есть в его условии A.column1 = B.column1. А надо бы != но если так написать, то просто перемножение таблиц за вычетом одинаковых строк произойдет. Такая же ерунда, если where с != сделать, а надо бы что-то вроде where A.column1 is not IN B если бы был такой синтаксис

Говоря человеческим языком, надо найти в таблице A записи, которых нет в B (сами структуры таблиц немного отличаются).

Такое вообще можно?

★★★★★

Последнее исправление: praseodim (всего исправлений: 6)

что-то вроде where A.column1 is not IN B если бы был такой синтаксис

Типа вложенные запросы? SELECT * FROM A WHERE column1 NOT IN (SELECT column1 FROM B)

Но вообще это каким-то вариантом джойна решается по идее

MrClon ★★★★★
()

Left join ... where b.id is null что-ли?

anonymous
()
Ответ на: комментарий от looper

Да, вроде получилось. Чего-то я просто запутался немного.

Спасибо всем за подсказки!

praseodim ★★★★★
() автор топика

Как вариант:

select A.* from A left join B on (A.column1 = B.column1) where B.id is null;
Miguel ★★★★★
()
Ответ на: комментарий от slovazap

Правильный ответ использовать NOT EXISTS

anonymous
()
Ответ на: комментарий от Deleted

Не поможет. По смыслу картинок помог бы left join, но увы. И там вообще-то имена столбцов разные, даже тип не совсем одинаковый и вообще таблица B - это уже результат join, я просто не стал усложнять в исходном сообщении.

Вот от MrClon сработало. И оно может не совсем хорошо, как заметил slovazap но в моем случае все нормально было. Собственно, я даже как бы знал этот вариант, упомянув про NOT IN, но затупил сильно.

Еще раз спасибо за подсказки.

praseodim ★★★★★
() автор топика
Ответ на: комментарий от crutch_master

Вообще-то ms sql. // И покраснел ;-) Ну пришлось.

Впрочем для данного случая не важно было. Ничего специфичного не было, запросы не регулярные, база скромная по размерам, всего где-то 500K записей. И отработало быстро даже без оптимизаций.

praseodim ★★★★★
() автор топика
Последнее исправление: praseodim (всего исправлений: 1)
Ответ на: комментарий от praseodim

А в чем увы-то, объясни(-те). Джойнить с результатом джойна не запрещено.

select a.*
from a
left join (
  select
    c.column as column,
    1 as present
  from c
  inner join d
    on c.d_id = d.id
) b
  on a.column = b.column
where b.present is null
anonymous
()
Ответ на: комментарий от praseodim

Запрос вида

SELECT * FROM A WHERE column1 NOT IN (SELECT column1 FROM B)
должен тоже отработать нормально,только надо учесть, что в отличие от от конструкции c
NOT EXISTS
в которой для каждой строки из таблицы A ищется всего одна строка из таблицы B, производится выборка всех строк из таблицы B для одной записи из таблицы A. Если данных не много, то вполне нормально, в противном случае тормозить будет выборка.

anonymous
()
Ответ на: комментарий от anonymous

left join правильней всего, по-моему. Not exist оптимизатор приведёт к left join, если достаточно умный, а если недостаточно, то будет по каждому id одной таблицы лезть в другую вместо одновременного итерирования по двум таблицам.

Sorcerer ★★★★★
()
Ответ на: комментарий от anonymous

Про join не знаю - надо планы смотреть, но скорее всего тоже должно работать. Поинт в том что NOT IN - точно нет.

slovazap ★★★★★
()
Ответ на: комментарий от Sorcerer

left join у меня почему-то не сработал. Вернее результат join и left join был одинаковым (как и right join). Может это мелкомягкие приколы такие, может я чего не понял.

praseodim ★★★★★
() автор топика
Ответ на: комментарий от praseodim

Может порядок джойнов сыграл? Ты часом не «from a left join b on expr inner join c on expr» делал без субселекта или скобок?

anonymous
()
Ответ на: комментарий от Deleted

Почитал каменты. Стало грустно. Если трудно читать книжки, может хоть картинка поможет ))
https://external-preview.redd.it/M5QHWsp2vgZ-3QDZ4m-qS58lsOUgDNHau8trSFzS8H0....

Картинка - чушь собачья. Операция джоина - это не пересечение множеств, это перемножение матриц, а это принципиально иная операция, дающая произведение размерностей вместо сохранения размерности на картинке.

byko3y ★★★★
()
Ответ на: комментарий от anonymous

А левый джойн с нулл фильтром - неправильный ответ? В чем разница будет?

Оптимизаторы на хороших движках такой нулл-фильтр просто закидывает в условия джоина, и разница оказывается никакая.

byko3y ★★★★
()
Ответ на: комментарий от Sorcerer

left join правильней всего, по-моему. Not exist оптимизатор приведёт к left join, если достаточно умный, а если недостаточно, то будет по каждому id одной таблицы лезть в другую вместо одновременного итерирования по двум таблицам.

SELECT * FROM A WHERE column1 NOT IN (SELECT column1 FROM B).
и.
SELECT A.* FROM A LEFT JOIN B ON (A.column1 = B.column1) WHERE B.id is null.
внезапно, выдают разные результаты.
Если в таблице B есть индекс по id, то обычно оба запроса будут использовать именно его, таким образом выдавая разные результаты с равной скоростью.

byko3y ★★★★
()
Ответ на: комментарий от Sorcerer

Я про not exist говорил, а не про not in

Вот они как раз примерно одинаковые по функциям, хоть not in в некоторых СУБД плохо обрабатывается. Ну то есть, например, в PostgreSQL и Firebird если у тебя хоть одно значение из вложенного запроса NULL, то not in возвращает «ложь» независимо от остальных значений.

byko3y ★★★★
()
Ответ на: комментарий от byko3y
SELECT * FROM A WHERE column1 NOT IN (SELECT column1 FROM B).
и.
SELECT A.* FROM A LEFT JOIN B ON (A.column1 = B.column1) WHERE B.id is null.

так ты это, делаешь чушь надо так

SELECT A.* FROM A LEFT JOIN B ON (A.column1 = B.column1) WHERE B.column1 is null.

jo_b1ack ★★★★★
()
Последнее исправление: jo_b1ack (всего исправлений: 1)
Ответ на: комментарий от byko3y

Картинка - чушь собачья. Операция джоина - это не пересечение множеств, это перемножение матриц

Ты больной, ты сам чушь собачью сказал, нет там перемножения матриц, там даже матриц нет!

anonymous
()
Ответ на: комментарий от HIS

Матрицы в алгоритмах тупого перебора?

А что не так? Произведение является комбинацией каждого элемента одного отношения с другим. Можно называть это векторами, но векторы - это подвид матрицы. Произведение коротежей - это тупо их объединение. По крайней мере что угодно из этого лучше упомянутой выше картинки, которая только запутывает, а не поясняет.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

А что не так?

Да всё не так!

Произведение является комбинацией каждого элемента одного отношения с другим.

Умножение матриц A B, реже со знаком умножения A × B — есть операция вычисления матрицы C, каждый элемент которой равен сумме произведений элементов в соответствующей строке первого множителя и столбце второго.

Количество столбцов в матрице A должно совпадать с количеством строк в матрице B, иными словами, матрица A обязана быть согласованной с матрицей B. Если матрица A имеет размерность m × n, B — n × k, то размерность их произведения A B = C есть m × k.

Можно называть это векторами, но векторы - это подвид матрицы.

Кончай чушь пороть, ей больно. Тебе можно нормальным назвать, но у тебя явное слабоумие!

Произведение коротежей - это тупо их объединение.

Неверно. Соединение ­— это декартово произведение множеств кортежей и выборка по предикату отношения!

У нас реляционная алгебра, а не матричная, и у нас это множества, а не матрицы!

anonymous
()

Говоря человеческим языком, надо найти в таблице A записи, которых нет в B (сами структуры таблиц немного отличаются).

Тебе уже сказали про NOT IN, годится для единичных/ручных запросов, но этот тип запросов убийца перформанса, никак тут индексы не участвуют.

anonymous
()
Ответ на: комментарий от t184256

Ты матричное произведение с декартовым попутал.

Нет он попутал посимвольное сравнение с умножением.

HIS
()
Ответ на: комментарий от byko3y

Вот например - вопрос на засыпку (да лично тебе). Как бы ты наиболее оптимально сравнивал строки на не схожесть?

HIS
()
Ответ на: комментарий от HIS

Я думал строки - это наборы символов. Ты про исходную задачу ОП-а?
SELECT * FROM A WHERE NOT EXISTS (SELECT B.column1 FROM B WHERE A.column1 = B.column1)
Естественно, должен быть индекс по column1 в B.

byko3y ★★★★
()
Ответ на: комментарий от HIS

Оптимизатор сам за меня говорит:
PLAN (T_911973 INDEX (XT_911973_SERVER_ID))
PLAN (R NATURAL)
Последовательный проход по таблице A с проверкой условия вспомогательным запросом по индексу в таблице B.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Картинка - чушь собачья. Операция джоина - это не пересечение множеств, это перемножение матриц, а это принципиально иная операция, дающая произведение размерностей вместо сохранения размерности на картинке.

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

надеюсь инженерное любопытство возьмёт верх над юношеским максимализмом.

Deleted
()
Ответ на: комментарий от Deleted

Джойнить не только по (column = column) можно, так что формально картина шире, чем на картинке.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.