У меня есть следующие две таблицы 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 |
+----+------+--------------+
Любая помощь будет высоко оценена.
Существует несколько разных способов сделать это с различной эффективностью в зависимости от того, насколько хорош ваш оптимизатор запросов и относительный размер двух таблиц:
Это кратчайший оператор и может быть самым быстрым, если ваша телефонная книга очень короткая:
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
(игнорируя, что, как говорили другие, обычно лучше всего выбирать только нужные столбцы, а не "*
" )
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 *", потому что он может нарушить ваш код, если кто-то изменяет основные таблицы или представления (и это неэффективно).
Нижеприведенный код будет немного более эффективным, чем приведенные выше ответы при работе с более крупными наборами данных.
SELECT * FROM Call WHERE
NOT EXISTS (SELECT 'x' FROM Phone_book where
Phone_book.phone_number = Call.phone_number)
Call
, если в Phone_book
есть несколько совпадающих строк. То есть, если между вашими двумя таблицами есть отношение 1:N
Я думаю,
SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON
CALL.id = Phone_book.id WHERE Phone_book.name IS NULL
id
в таблице call
не совпадает со значением столбца id
в таблице Phone_book
, поэтому вы не можете присоединиться к этим значениям. Смотрите ответ WOPR для аналогичного подхода.
SELECT DISTINCT Call.id
FROM Call
LEFT OUTER JOIN Phone_book USING (id)
WHERE Phone_book.id IS NULL
Это вернет лишние идентификаторы, отсутствующие в таблице Phone_book.
SELECT name, phone_number FROM Call a
WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b)
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
В качестве альтернативы,
select id from call
minus
select id from phone_number