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 |
+-----------+----------+------------+

Приклад виведення рядків у таблиці1, які не є в таблиці2:

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

Можливо, щось подібне має спрацювати:

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

Відповіді:


96

Якщо у вас є 300 стовпців, як ви згадували в іншому коментарі, і ви хочете порівнювати всі стовпці (якщо припустити, що стовпці мають однакове ім’я), ви можете використовувати 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 стовпців, вам слід переробити базу даних.
Іхароб Аль Асімі

Ей, це працює і для мене, дякую! але чи це буде проблема, якщо рядки> 300, як ви згадали вище?
thekucays

Я все ще плутаю запит btw..що, якщо я зміню "де b.FirstName є нульовим" на "де b.LastName є нульовим", наприклад? яка різниця? Мені шкода, що прошу це, я все ще нова у sql: D
thekucays

184

Вам потрібно зробити підбір на основі імені стовпця, а не *.

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

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

Для отримання додаткових прикладів зверніться до синтаксису підзапиту MySQL .


1
дякую за роз’яснення! але мені дійсно не потрібно базувати вибір рядків на будь-якому полі, тому що мене цікавить будь-яка зміна будь-якого поля в рядку ...

Якщо для порівняння є лише кілька стовпців, ви можете зробити приєднання згідно з прикладом @ Стіва. Якщо ви насправді запитуєте про загальне порівняння даних у двох таблицях з багатьма стовпцями, ви, ймовірно, хочете шукати інструмент розрізнення MySQL .
Stennie

2
Зауважте, що це завжди буде повертати порожній набір, якщо стовпець, який ви дивитесь у таблиці2, містить нулі. Це не проблема, якщо ви робите це на основі первинного ключа, але стосується людей, які намагаються використовувати цей запит в інших контекстах.
Марк Амері

4
Але що робити, якщо ми говоримо про великі дані? А таблиця2 містить 100М рядків, наприклад?
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

Сильний. Найкраща відповідь для великих наборів даних
Ian Chadwick

35

Стандартна СПІЛЬНА СПОЛУЧЕННЯ може вирішити проблему, і, якщо поля при приєднанні індексуються,
також повинна бути швидшою

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

Я згоден, чудова відповідь. У мене є людина, що складається з чотирьох людей, між чотирма таблицями, введення І в внутрішнє з'єднання, безумовно, буде більш економічним.
ДР.

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.