Как сравнить 2 таблицы в sql
Перейти к содержимому

Как сравнить 2 таблицы в sql

  • автор:

Как сравнить две таблицы sql

Для работы с данными из нескольких таблиц можете попробовать следующие варианты.

Оператор JOIN используется для объединения двух таблиц по определенному условию, например, по ключевому полю. Следующий запрос объединяет две таблицы table1 и table2 по столбцу id и выбирает все строки, где значения в столбцах column1 и column2 совпадают:

Оператор EXCEPT используется для вычитания одной таблицы из другой. Следующий запрос выбирает все строки из таблицы table1 , которых нет в таблице table2 :

Еще есть оператор UNION для объединения строк из двух таблиц, но это не сравнение таблиц, а скорее склейка данных из них.

Сравнение двух таблиц по содержимому в SQL

Как сравнить две одинаковые по структуре но различающиеся по содержимому таблицы.

1563389000423

SELECT *
FROM base1 a
LEFT JOIN base2 b ON a.id = b.id

1563390595035

В этом примере вместо отсутствующих значений получим NULL.

Запрос с использованием функции EXCEPT

SELECT * FROM test1

SELECT * FROM test2

вернет тот же результат что и запрос

SELECT * FROM test2
WHERE id NOT IN (SELECT id FROM test1)

1563391464558

В данном случае будут отображены только те строки. которые не совпадают.

SQL-Ex blog

Недавно мы рассматривали сравнение схем с помощью Azure Data Studio. Что если нам потребуется сравнение таблиц с помощью запроса? В этой статье мы сравним использование EXCEPT, NOT IN, и NOT EXISTS для нахождения различий в двух таблицах.

Мы будем сравнивать две таблицы Comic и Comic_Copy. В Comic содержится на 48 строк больше, чем в Comic_Copy. Давайте найдем отличие.

EXCEPT

Давайте начнем сравнение с EXCEPT. При использовании EXCEPT мы захотим иметь одинаковое число и порядок столбцов, а также одинаковые типы данных. Мы удовлетворяем этим критериям в нашем примере, поэтому давайте выполним наш запрос и посмотрим на результаты:

SELECT Id,Title 
FROM Comic
EXCEPT
SELECT Id,Title
FROM Comic_Copy;
GO

Мы видим 48 строк, что правдоподобно, исходя из подсчетов, которые мы рассматривали ранее.

NOT IN

Теперь мы будем использовать NOT IN для сравнения таблиц. Выберем Id из таблицы Comic, и будем использовать подзапрос, чтобы получить идентификаторы в Comic_Copy:

SELECT Id, Title 
FROM Comic
WHERE Id NOT IN (
SELECT Id
FROM Comic_Copy
);
GO

Мы опять получаем наши 48 строк.

NOT EXISTS

Наконец, давайте проверим NOT EXISTS.

SELECT Id, Title 
FROM Comic AS c
WHERE NOT EXISTS (
SELECT 1
FROM Comic_Copy AS cc
WHERE cc.Id = c.Id
);
GO

Что работает лучше?

Если мы выполним все три запроса вместе, какой покажет себя лучше остальных?

EXCEPT не кажется лучшим вариантом, в то время как два других варианта демонстрируют одинаковый план. Мы работаем с относительно небольшим набором данных, поэтому выполнение каждого запроса занимает менее секунды с одним и тем же числом логических чтений.

Хотя NOT IN и NOT EXISTS работают по-разному. Для NULL-значений NOT IN не вернет записей, поскольку NULL-значения не трактуются как сравниваемые. При использовании NOT EXISTS NULL также будут возвращаться.

Если мы изменим одно из значений title на NULL:

UPDATE Comic 
SET Title = NULL
WHERE /> GO

и выполним запросы на сравнение по Title, то получим разные результаты. NOT IN даст нам 47 строк:

А NOT EXISTS по-прежнему дает 48:


Переходим на NOT EXISTS

Мы рассмотрели три разных метода нахождения различий между таблицами. Все три варианта с использованием EXCEPT, NOT IN и NOT EXISTS могут выполнить работу, но разными способами. NOT EXISTS был бы моим «выбором» для оптимального поиска различий, но имейте в виду наличие NULL при сравнении с помощью NOT IN.

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Автор не разрешил комментировать эту запись

Как сравнивать две произвольные таблицы?

Добрый день!
Есть две таблицы. Известно, что большая часть данных в них пересекается. Но могут быть и совсем разные данные или измененные данные в одной из таблиц. Необходимо написать алгоритм по которому бы программа находила общие записи в таблицах и отображала. Как бы для начала подойти к этой задаче?

  • Вопрос задан более трёх лет назад
  • 13408 просмотров

Комментировать
Решения вопроса 0
Ответы на вопрос 4

oleg_agapov

Oleg Agapov @oleg_agapov
Data analyst, Business Intelligence

Всё-таки Java или SQL? 🙂
Если таки SQL. Подразумеваю, что используется Оракл.
Во-первых, если таблицы не большие, то не должно быть проблем с обычным джойном или декартовым произведением

SELECT t1.*, t2.* FROM table1 t1, table2 t2 WHERE t1.fields = t2.fields

Если таблицы большие, тут нужно быть аккуратнее, чтоб не пошел фулл скан таблиц и все не зависло к чертям. Убедитесь, что в таблице есть индексы. Вам повезло, если индексы совпадают с теми полями, по которым нужно сравнивать.
Далее, я бы «откусывал» небольшие куски одной из таблиц и джойнил бы другую либо как в первом примере, либо вложенным подзапросом в SELECT. Если не критично для быстродействия, понемногу добавлял бы бОльшие куски первоначальной таблицы. Опять же, если не тормозит — то ок. В противном случае — писал бы процедуру для разбиения на куски и последующего джойна.

Ответ написан более трёх лет назад
Нравится 1 4 комментария

Если Оракл и если таблицы большие, то индексы не нужны — все равно нужно сравнить между собой ПОЛНОСТЬЮ всё. Лучше в этом случае распараллелить запрос на 4-32 потока, смотря — сколько ресурсов у сервера есть и сколько из них можно утилизировать.

oleg_agapov

Oleg Agapov @oleg_agapov

Борис: Совершенно верно, но я знаком с Map Reduce только в теории. Поэтому бы и использовал индекс, чтобы разбивать на куски (по сути — потоки) и прогонял бы по очереди. А искать известную часть одной таблицы все-таки лучше по индексу второй.

Oleg Agapov: ну опять-таки неоднозначно =) если, например, нужен кусок 100-миллионный кусок таблицы на 1 млрд записей («жалкие» 10%), то индексы лучше не использовать, т.к. время запроса, скорее всего, увеличится по сравнению с фуллсканом. Что касается разбиения на куски и дальнейшей параллельной обработки, то идея хорошая. Я примерно о том же и говорил: Oracle позволяет запустить запрос в несколько потоков (сессий).

Если выполнятся следующие условия:
1) нужен фул-скан;
2) таблицы огромные а ресурсы сервера слабые относительно объема таблиц;
3) таблицы разбиты на партиции (например по дате);

То можно запустить сверку в цикле по дате с загрузкой результата каждой итерации во временную таблицу, или выводом данныx в dbms_output (Oracle). Таким образом не будет эффекта зависшей БД, и не нужно будет гадать отработает ли вообще когда нибудь данный запрос и «рубить или не рубить» . Работа будет делаться маленькими порциями-партициями и даже в случае сбоя можно будет продолжить с «места разъединения».

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *