Как выбрать строки без соответствующей записи в другой таблице? - PullRequest
267 голосов
/ 02 ноября 2010

Я выполняю некоторые работы по обслуживанию приложения базы данных и обнаружил, что радость от радости, даже несмотря на то, что значения из одной таблицы используются в стиле внешних ключей, для таблиц нет ограничений по внешнему ключу.

Я пытаюсь добавить ограничения FK для этих столбцов, но я нахожу это, потому что в таблицах уже есть масса плохих данных из предыдущих ошибок, которые были наивно исправлены, мне нужно найтистроки, которые не совпадают с другой таблицей, а затем удаляют их.

В Интернете я нашел несколько примеров такого рода запросов, но, похоже, все они дают примеры, а не объяснения, иЯ не понимаю, почему они работают.

Может кто-нибудь объяснить мне, как построить запрос, который возвращает все строки без совпадений в другой таблице, и что он делает, чтобы я мог сам выполнить эти запросывместо того, чтобы прибегать к SO для каждой таблицы в этом беспорядке , которая не имеет ограничений FK?

Ответы [ 9 ]

507 голосов
/ 02 ноября 2010

Вот простой запрос:

SELECT t1.ID
FROM Table1 t1
    LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL

Ключевые моменты:

  1. LEFT JOIN;это вернет ВСЕ строки из Table1, независимо от того, есть ли соответствующая строка в Table2.

  2. Предложение WHERE t2.ID IS NULL;это ограничит возвращаемые результаты только теми строками, в которых идентификатор, возвращаемый из Table2, равен нулю - другими словами, в Table2 есть запись NO для этого конкретного идентификатора из Table1.Table2.ID будет возвращено как NULL для всех записей из Table1, где идентификатор не совпадает в Table2.

63 голосов
/ 18 апреля 2016

Я бы использовал выражение 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)
10 голосов
/ 31 мая 2016
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)

В таблице 1 есть столбец, к которому вы хотите добавить ограничение внешнего ключа, но значения в foreign_key_id_column не все совпадают с id в таблице 2.

  1. При первоначальном выборе перечислены id s из таблицы1.Это будут строки, которые мы хотим удалить.
  2. Предложение NOT IN в операторе where ограничивает запрос только теми строками, в которых значение в foreign_key_id_column отсутствует в списке таблицы 2 id s.
  3. Оператор SELECT в круглых скобках получит список всех id s в таблице 2.
7 голосов
/ 16 апреля 2015

Где T2 - это таблица, к которой вы добавляете ограничение:

SELECT *
FROM T2
WHERE constrained_field NOT
IN (
    SELECT DISTINCT t.constrained_field
    FROM T2 
    INNER JOIN T1 t
    USING ( constrained_field )
)

И удаляете результаты.

3 голосов
/ 14 января 2018

Пусть у нас есть следующие 2 таблицы (зарплата и работник) enter image description here

Теперь я хочу получить из таблицы сотрудников те записи, которых нет в зарплате. Мы можем сделать это тремя способами:

  1. Использование внутреннего соединения
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

1 голос
/ 21 декабря 2018

Из аналогичного вопроса здесь Запрос внутреннего соединения MySQL для получения записей, отсутствующих в другой таблице Я получил это на работу

SELECT * FROM bigtable 
LEFT JOIN smalltable ON bigtable.id = smalltable.id 
WHERE smalltable.id IS NULL

smalltable - это место, где у вас отсутствуют записи, bigtable - это место, где у вас есть все записи. В списке запросов перечислены все записи, которые не существуют в smalltable, но существуют в bigtable. Вы можете заменить id любым другим подходящим критерием.

0 голосов
/ 14 ноября 2018

Вы можете выбрать Просмотры , как показано ниже:

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]
0 голосов
/ 06 июня 2018

Как выбрать строки без соответствующей записи в обеих таблицах?


    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

0 голосов
/ 25 января 2018

Я не знаю, какой из них оптимизирован (по сравнению с @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);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...