Логическая разность запросов в MySQL

Опубликовано Опубликовано в рубрике PHP, SQL

Приветствую Вас, дорогие читатели моего блога. Прошу прощения за столь долгий перерыв в написании постов.

Сегодня речь пойдёт о том, как получить различающиеся значения результатов идентичных запросов к различным таблицам БД.
Начнем с постановки задачи. У нас есть две таблицы A и B (пусть даже из различных БД), в которых хранится некая информация . В соответствии с правилами нормализации структуры каждой записи присваивается ID. Нам необходимо создать некий механизм, который при загрузке приложения будет проверять наличие новых записей в таблице B, брать данные из них и дописывать в таблицу A.

Алгоритмически решение получается несложное. В таблице A помимо своих ID записываются соответствующие ID из таблицы B. При появлении в B новых строк мы берем их ID и записываем по ним данные в таблицу A. Но как узнать, что новая запись появилась, если мы оперируем только ID? В этом нам поможет такая операция, как разность множеств.

Разность множеств X и Y — это множество, состоящее из всех элементов множества X, не входящих во множество Y. Таким образом в разность таблиц B и A (подчеркиваю порядок вхождения множеств!) войдут все строки таблицы B, которых нет в таблице A.

Теперь перейдем к реализации этого алгоритма. Практика показала, что одного SQL тут будет недостаточно. А значит, мы должны применить PHP. Сами по себе запросы сделаем тривиальными — они будут получать все уникальные ID таблицы B в индексные массивы $array_a и $array_b соответственно:

SELECT `id_B` FROM `A` GROUP BY `id_B`;
SELECT `id_B` FROM `B` GROUP BY `id_B`;

Далее нам поможет php-функция array_diff($array_b, $array_a). Она вернет массив $unique всех значений массива $array_b, которые не входят в $array_a.

При помощи foreach обойдём массив $unique, записав в строку $unique_string через запятую все полученные значения.

Теперь эту строку можно подать в запрос к таблице B. Таким образом, мы будем брать не всю информацию (а в масштабах больших проектов это критично), а лишь строго необходимую!

"SELECT * FROM `B` WHERE `id_B` IN (".$unique_string.")";

Полученный массив информации можно спокойно через тот же foreach и SQL-оператора INSERT записать в таблицу A!

Задача решена.

Послесловие. В MSSQL есть такая функция, как EXCEPT. Вызывается она подобно UNION между двух запросов:

(SELECT ...)
EXCEPT
(SELECT ...)

Она выполняет то же самое, что было описано выше, т.е. возвращает все различные значения, возвращенные левым запросом и отсутствующие в результатах выполнения правого запроса. Однако её нет в MySQL, что и привело меня к написанию данного поста =)

За сим всё!

Безошибочного Вам кода!

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

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