Mysql: выберите строки из таблицы, которых нет в другой

Как выбрать все строки в одной таблице, которых нет в другой?

Таблица 1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Таблица 2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Пример вывода для строк в таблице 1, которых нет в таблице 2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Может быть, что-то вроде этого должно работать:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)

person Community    schedule 01.08.2012    source источник


Ответы (7)


Если у вас есть 300 столбцов, как вы упомянули в другом комментарии, и вы хотите сравнить все столбцы (при условии, что все столбцы имеют одно и то же имя), вы можете использовать NATURAL LEFT JOIN для неявного соединения всех совпадающих имен столбцов между двумя таблицами, чтобы вам не нужно утомительно вводить все условия соединения вручную:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL
person Zane Bien    schedule 01.08.2012
comment
Обратите внимание, что это работает только тогда, когда ни один из столбцов не имеет значений NULL. В MySQL NULL != NULL, поэтому каждая строка, имеющая значение NULL, будет возвращена, даже если во второй таблице есть повторяющаяся строка. - person Kyle Kochis; 07.04.2015
comment
Если у вас 300 столбцов, вам следует перепроектировать базу данных. - person Iharob Al Asimi; 01.06.2016
comment
эй, это работает и для меня, спасибо! но будет ли это проблемой, если строк будет › 300, как вы упомянули выше? - person thekucays; 21.07.2016
comment
я все еще запутался в запросе, кстати... что, если я изменю, где b.FirstName имеет значение null, например, где b.LastName имеет значение null? какая разница? извините за вопрос, я все еще новичок в sql: D - person thekucays; 21.07.2016

Вам нужно сделать подзапрос на основе имени столбца, а не *.

Например, если у вас есть поле id, общее для обеих таблиц, вы можете сделать:

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

Дополнительные примеры см. в синтаксисе подзапросов MySQL.

person Stennie    schedule 01.08.2012
comment
Спасибо за разъяснения! но мне действительно не нужно основывать выбор строк на каком-либо поле, потому что меня интересуют любые варианты любого поля в строке... - person ; 02.08.2012
comment
Если есть только несколько столбцов для сравнения, вы можете выполнить объединение в соответствии с примером @Steve. Если вы на самом деле запрашиваете общее сравнение данных в двух таблицах со многими столбцами, вы, вероятно, захотите найти MySQL инструмент сравнения. - person Stennie; 02.08.2012
comment
Обратите внимание, что это всегда будет возвращать пустой набор, если столбец, который вы просматриваете в таблице 2, содержит нули. Не проблема, если вы делаете это на основе первичного ключа, но актуально для людей, пытающихся использовать этот запрос в других контекстах. - person Mark Amery; 17.11.2014
comment
Но что, если мы говорим о больших данных? А Table2 содержит 100M строк, например? - person frops; 18.05.2016
comment
Умный и умный ответ. Спасибо друг - person Anjana Silva; 18.07.2020

SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS поможет вам...

person Ruzbeh Irani    schedule 01.08.2012
comment
Хороший ответ, экономичный для больших наборов данных, спасибо. - person ekerner; 08.09.2014
comment
Сильный. Лучший ответ для больших наборов данных - person Ian Chadwick; 09.02.2016
comment
Спасибо, мне помогло - person logudotcom; 17.11.2020

Стандартное ЛЕВОЕ СОЕДИНЕНИЕ может решить проблему, и, если поля при объединении проиндексированы,
также должно быть быстрее

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null
person Steve    schedule 01.08.2012
comment
хорошо, я думаю, это должно быть так, кстати, почему WHERE t2.Birthdate Is Null вместо AND t1.Birthdate = t2.Birthdate? - person ; 02.08.2012
comment
Потому что если вы добавите это, то будет возвращена каждая строка, вы говорите, что в выводе должны появиться только строки, которых нет во второй таблице. - person Steve; 02.08.2012
comment
Это потрясающий ответ, так как он не требует возврата всех строк Table2! - person dotancohen; 08.12.2013
comment
Согласен, отличный ответ. У меня есть таблица «человек-многие» между 4 таблицами, поэтому размещение AND во внутреннем соединении определенно будет более экономичным. - person DR.; 08.12.2015

Пытаться:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL
person Sachin Pundir    schedule 08.12.2014

Попробуйте этот простой запрос. Это работает отлично.

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);
person Vijesh    schedule 30.10.2017

Это сработало для меня в Oracle:

SELECT a.* 
    FROM tbl1 a 
MINUS 
SELECT b.* 
    FROM tbl2 b;
person Gennady Sorochan    schedule 07.02.2017
comment
Вопрос был про MySQL. - person jelder; 27.02.2020