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


118

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

Таблица 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 |
+-----------+----------+------------+

Пример вывода для строк в Table1, которых нет в Table2:

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

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

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

Ответы:


96

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

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

Обратите внимание, что это работает должным образом, только когда ни один из столбцов не имеет значений NULL. В MySQL NULL! = NULL, поэтому каждая строка, имеющая значение NULL, будет возвращена, даже если есть повторяющаяся строка во второй таблице.
— Кайл Кочис

84
Если у вас 300 столбцов, вам следует изменить структуру базы данных.
— Iharob Al Asimi 01

эй, у меня тоже работает, спасибо! но будет ли это проблемой, если количество строк> 300, как вы упомянули выше?
— thekucays

Я все еще не понимаю, что такое запрос ... что, если я, например, изменю «где b.FirstName имеет значение null» на «где b.LastName равно null»? какая разница? извините, что спросил об этом, я все еще новичок в sql: D
— thekucays

184

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

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

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

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


1
Спасибо за разъяснения! но мне действительно не нужно основывать выбор строк на каком-либо поле, потому что меня интересуют любые варианты любого поля в строке ...

Если есть только несколько столбцов для сравнения, вы можете выполнить соединение, как в примере @ Steve. Если вы на самом деле запрашиваете общее сравнение данных в двух таблицах с множеством столбцов, вы, вероятно, захотите поискать инструмент сравнения MySQL .
— Стенни 01

2
Обратите внимание, что это всегда будет возвращать пустой набор, если столбец, который вы просматриваете в Table2, содержит нули. Не проблема, если вы делаете это на основе первичного ключа, но актуально для людей, пытающихся использовать этот запрос в других контекстах.
— Марк Эмери

4
Но что, если мы говорим о больших данных? А Table2 содержит, например, 100M строк?
— Frops

Умный и умный ответ. Спасибо, приятель
— Анджана Сильва

44
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 поможет вам...


2
Хороший ответ, экономичный для больших наборов данных, спасибо.
— ekerner 08

Strong. Лучший ответ для больших наборов данных
— Ян Чедвик,

35

Стандартное LEFT JOIN может решить проблему и, если поля при объединении проиндексированы,
также должно быть быстрее

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

хорошо, я думаю, это должно быть так, кстати, почему WHERE t2.Birthdate Is Nullвместо AND t1.Birthdate = t2.Birthdate?

Потому что, если вы добавите это, тогда будет возвращена каждая строка, вы говорите, что в выводе должны появиться только строки, не во второй таблице
— Стив

1
Это отличный ответ, так как он не требует возврата всех строк Table2!
— dotancohen

Согласен, отличный ответ. У меня есть таблица «человек-много» между 4 таблицами, размещение AND во внутреннем соединении определенно будет более экономичным.
— ДР.

6

Пытаться:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL

4

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

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.