SQL - поиск записей из одной таблицы, которых нет в другой
У меня есть следующие две таблицы SQL (в MySQL):
Phone_book
+----+------+--------------+
| id | name | phone_number |
+----+------+--------------+
| 1 | John | 111111111111 |
+----+------+--------------+
| 2 | Jane | 222222222222 |
+----+------+--------------+
Call
+----+------+--------------+
| id | date | phone_number |
+----+------+--------------+
| 1 | 0945 | 111111111111 |
+----+------+--------------+
| 2 | 0950 | 222222222222 |
+----+------+--------------+
| 3 | 1045 | 333333333333 |
+----+------+--------------+
Как узнать, какие вызовы были сделаны людьми, у которых phone_number
нет в Phone_book
? Желаемый результат:
Call
+----+------+--------------+
| id | date | phone_number |
+----+------+--------------+
| 3 | 1045 | 333333333333 |
+----+------+--------------+
Любая помощь будет высоко оценена.
Ответы
Ответ 1
Существует несколько разных способов сделать это с различной эффективностью в зависимости от того, насколько хорош ваш оптимизатор запросов и относительный размер двух таблиц:
Это кратчайший оператор и может быть самым быстрым, если ваша телефонная книга очень короткая:
SELECT *
FROM Call
WHERE phone_number NOT IN (SELECT phone_number FROM Phone_book)
в качестве альтернативы (благодаря Alterlife)
SELECT *
FROM Call
WHERE NOT EXISTS
(SELECT *
FROM Phone_book
WHERE Phone_book.phone_number = Call.phone_number)
или (благодаря WOPR)
SELECT *
FROM Call
LEFT OUTER JOIN Phone_Book
ON (Call.phone_number = Phone_book.phone_number)
WHERE Phone_book.phone_number IS NULL
(игнорируя, что, как говорили другие, обычно лучше всего выбирать только нужные столбцы, а не "*
" )
Ответ 2
SELECT Call.ID, Call.date, Call.phone_number
FROM Call
LEFT OUTER JOIN Phone_Book
ON (Call.phone_number=Phone_book.phone_number)
WHERE Phone_book.phone_number IS NULL
Следует удалить подзапрос, позволяя оптимизатору запросов работать с его магией.
Кроме того, избегайте "SELECT *", потому что он может нарушить ваш код, если кто-то изменяет основные таблицы или представления (и это неэффективно).
Ответ 3
Нижеприведенный код будет немного более эффективным, чем приведенные выше ответы при работе с более крупными наборами данных.
SELECT * FROM Call WHERE
NOT EXISTS (SELECT 'x' FROM Phone_book where
Phone_book.phone_number = Call.phone_number)
Ответ 4
Я думаю,
SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON
CALL.id = Phone_book.id WHERE Phone_book.name IS NULL
Ответ 5
SELECT DISTINCT Call.id
FROM Call
LEFT OUTER JOIN Phone_book USING (id)
WHERE Phone_book.id IS NULL
Это вернет лишние идентификаторы, отсутствующие в таблице Phone_book.
Ответ 6
SELECT t1.ColumnID,
CASE
WHEN NOT EXISTS( SELECT t2.FieldText
FROM Table t2
WHERE t2.ColumnID = t1.ColumnID)
THEN t1.FieldText
ELSE t2.FieldText
END FieldText
FROM Table1 t1, Table2 t2
Ответ 7
SELECT name, phone_number FROM Call a
WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b)
Ответ 8
В качестве альтернативы,
select id from call
minus
select id from phone_number