Поиск записей в одной таблице, которым нет соответствия в другой таблице

Вариантов для выборки строк из таблицы, для которых нет соответствия в другой таблице я знаю три.

Если ваша СУБД не умеет выполнять вложенные запросы (например MySQL версий ниже 4.1), то выбор у вас только один:

SELECT *
 FROM table1 LEFT JOIN table2 ON table1.id=table2.id
 WHERE table2.id IS NULL;

Если же вы используете полноценную СУБД, ну по крайней мере умеющую выполнять подзапросы SELECT, то кроме вышеназваного варианта, есть еще два. Один построен с использованием конструкции NOT IN, другой с использованием NOT EXISTS.

SELECT *
 FROM table1
 WHERE id NOT IN (SELECT id FROM table2 WHERE id IS NOT NULL);
SELECT *
 FROM table1
 WHERE NOT EXISTS (SELECT id FROM table2 WHERE id=table1.id);

По скорости исполнения вариант с LEFT JOIN сильно проигрывает вариантам со вложеными запросами. Вариант с NOT IN всегда быстрее варианта с NOT EXIST в случаях, когда число записей в таблице table1 больше числа записей в таблице table2. В противном случае, NOT IN оказывается быстрее только на таблицах с небольшим числом записей, а на больших объемах уже проигрывает NOT EXIST. Причем чем больше записей в таблице table2 тем существеннее разница в скорости выполнения. Но только при наличии индекса по полю id!

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

Поделиться в FacebookДобавить в TwitterДобавить в Telegram

Комментарии

  1. (#)   Евгений:

    Хочу добавить замечание к запросу NOT IN:
    подзапрос должен иметь вид (SELECT id FROM table2 WHERE id IS NOT NULL), иначе результат будет неверным


  2. (#)   Dimka:

    Евгений, спасибо!

    Исправил.


  3. (#)   Сергей:

    Мужик, спасибо тебе!
    Очень помогла статья))


  4. (#)   inverser:

    Благодарю, друг!


  5. (#)   andrey mailinator:

    а еще можно с WITH сделать. Тоже неплохой вариант и даже более читабельный чем со сложенными запросами. Но только для Mysql версии 8 и выше:

    WITH tab2 AS ( SELECT id FROM table2 WHERE id=table1.id
    )
    SELECT * FROM table1 JOIN tab2 ON table1.id=tab.id WHERE NOT EXISTS tab2;


Оставить комментарий

Ответ на Поиск записей в одной таблице, которым нет соответствия в другой таблице