Как выбрать строки без соответствующей записи в другой таблице?
Я делаю некоторые работы по обслуживанию приложения базы данных, и я обнаружил, что радость радостей, хотя значения из одной таблицы используются в стиле внешних ключей, ограничений на внешние ключи для таблиц нет.
Я пытаюсь добавить ограничения FK для этих столбцов, но я нахожу это, потому что в таблицах из предыдущих ошибок, которые были наивно исправлены, уже существует целая загрузка плохих данных, мне нужно найти строки, которые не совпадают с другой таблицей, а затем удаляют их.
Я нашел несколько примеров такого рода запросов в Интернете, но все они, кажется, приводят примеры, а не объяснения, и я не понимаю, почему они работают.
Может кто-нибудь объяснить мне, как построить запрос, который возвращает все строки без совпадений в другой таблице, и что он делает, чтобы я мог самостоятельно выполнять эти запросы, а не прибегать к SO для каждой таблицы в этом беспорядок, который не имеет ограничений FK?
Ответы
Ответ 1
Вот простой запрос:
SELECT t1.ID
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL
Ключевыми моментами являются:
-
LEFT JOIN
; это вернет ВСЕ строки из Table1
, независимо от того, есть ли соответствующая строка в Table2
.
-
Предложение WHERE t2.ID IS NULL
; это ограничит результаты, возвращаемые только тем строкам, где идентификатор, возвращаемый из Table2
, равен нулю - другими словами, в Table2
есть запись NO для этого идентификатора из Table1
. Table2.ID
будет возвращен как NULL для всех записей из Table1
, где идентификатор не сопоставляется в Table2
.
Ответ 2
Я бы использовал выражение EXISTS
, так как оно более мощное, вы можете точнее выбрать строки, которые хотите присоединиться, в случае из LEFT JOIN
вам нужно взять все, что в объединенной таблице. Его эффективность, вероятно, такая же, как в случае LEFT JOIN
с нулевым тестом.
SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)
Ответ 3
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)
В таблице 1 есть столбец, к которому вы хотите добавить ограничение внешнего ключа, но значения в foreign_key_id_column
не все совпадают с id
в таблице 2.
- Первоначальный выбор перечисляет
id
из таблицы1. Это будут строки, которые мы хотим удалить. - Предложение
NOT IN
в операторе where ограничивает запрос только теми строками, в которых значение foreign_key_id_column
отсутствует в списке id
таблицы 2. - Оператор
SELECT
в круглых скобках получит список всех id
которые находятся в таблице 2.
Ответ 4
Где T2
- таблица, к которой вы добавляете ограничение:
SELECT *
FROM T2
WHERE constrained_field NOT
IN (
SELECT DISTINCT t.constrained_field
FROM T2
INNER JOIN T1 t
USING ( constrained_field )
)
И удалите результаты.
Ответ 5
Пусть у нас есть следующие 2 таблицы (зарплата и работник) ![enter image description here]()
Теперь я хочу те записи из таблицы сотрудников, которых нет в зарплате. Мы можем сделать это тремя способами:
- Использование внутреннего соединения
select * from employee
where id not in(select e.id from employee e inner join salary s on e.id=s.id)
![enter image description here]()
- Использование левого внешнего соединения
select * from employee e
left outer join salary s on e.id=s.id where s.id is null
![enter image description here]()
- Использование полного соединения
select * from employee e
full outer join salary s on e.id=s.id where e.id not in(select id from salary)
![enter image description here]()
Ответ 6
От подобного вопроса здесь MySQL Внутренний Запрос Соединения, чтобы Получить Записи, Не Представленные в Другой Таблице, я получил это, чтобы работать
SELECT * FROM bigtable
LEFT JOIN smalltable ON bigtable.id = smalltable.id
WHERE smalltable.id IS NULL
smalltable
- это место, где у вас отсутствуют записи, bigtable
- это место, где у вас есть все записи. В списке запросов перечислены все записи, которые не существуют в smalltable
но существуют в bigtable
. Вы можете заменить id
любым другим подходящим критерием.
Ответ 7
Я не знаю, какой из них оптимизирован (по сравнению с @AdaTheDev), но этот, кажется, быстрее, когда я использую (по крайней мере, для меня)
SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2
Если вы хотите получить любой другой конкретный атрибут, вы можете использовать:
SELECT COUNT(*) FROM table_1 where id in (SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2);
Ответ 8
Вы можете выбрать Просмотры, как показано ниже:
CREATE VIEW AuthorizedUserProjectView AS select t1.username as username, t1.email as useremail, p.id as projectid,
(select m.role from userproject m where m.projectid = p.id and m.userid = t1.id) as role
FROM authorizeduser as t1, project as p
а затем поработайте над представлением для выбора или обновления:
select * from AuthorizedUserProjectView where projectid = 49
что дает результат, как показано на рисунке ниже, то есть для несоответствующего столбца был заполнен нуль.
[Result of select on the view][1]
Ответ 9
Вы можете сделать что-то вроде этого
SELECT IFNULL('price'.'fPrice',100) as fPrice,product.ProductId,ProductName
FROM 'products' left join 'price' ON
price.ProductId=product.ProductId AND (GeoFancingId=1 OR GeoFancingId
IS NULL) WHERE Status="Active" AND Delete="No"
Ответ 10
Как выбрать строки без соответствующей записи в таблице "Оба"?
select * from [dbo].[EmppDetails] e
right join [Employee].[Gender] d on e.Gid=d.Gid
where e.Gid is Null
union
select * from [dbo].[EmppDetails] e
left join [Employee].[Gender] d on e.Gid=d.Gid
where d.Gid is Null