Jak wybrać wiersze bez pasującego wpisu w innej tabeli?
Wykonuję pewne prace konserwacyjne nad aplikacją bazodanową i odkryłem, że joy of joys, mimo że wartości z jednej tabeli są używane w stylu kluczy obcych, nie ma ograniczeń dla kluczy obcych na tabelach.
Staram się dodać do tych kolumn ograniczenia FK, ale stwierdzam, że, ponieważ jest już cały ładunek złych danych w tabelach z poprzednich błędów, które zostały naiwnie poprawione, muszę znaleźć wiersze, które nie pasują do innych tabeli, a następnie je usunąć.
Znalazłem kilka przykładów tego rodzaju zapytań w sieci, ale wszystkie wydają się dostarczać przykładów, a nie wyjaśnień i nie rozumiem, dlaczego działają.
Czy ktoś może mi wyjaśnić, jak skonstruować zapytanie, które zwraca wszystkie wiersze bez dopasowania w innej tabeli i co robi, tak, że mogę te zapytania zrobić sam, zamiast przybiegać do SO dla każdej tabeli w tym bałagan , który nie ma ograniczeń FK?
7 answers
Oto proste zapytanie:
SELECT t1.ID
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL
Kluczowe punkty to:
LEFT JOIN
zwraca wszystkie wiersze zTable1
, niezależnie od tego, czy wTable2
jest pasujący wiersz.Klauzula
WHERE t2.ID IS NULL
; spowoduje to ograniczenie wyników zwracanych tylko do tych wierszy, w których ID zwrócone zTable2
jest null - innymi słowy nie ma rekordu wTable2
dla tego konkretnego ID zTable1
.Table2.ID
zostanie zwrócona jako NULL dla wszystkich rekordów zTable1
gdzie ID nie jest dopasowane wTable2
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 12:59:21
Użyłbym EXISTS
wyrażenie ponieważ jest bardziej wydajne, możesz dokładniej wybrać wiersze, które chcesz połączyć, w przypadku LEFT JOIN
musisz wziąć wszystko, co znajduje się w tabeli joined. Jego sprawność jest prawdopodobnie taka sama jak w przypadku {[2] } z testem null.
SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-18 12:48:18
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)
Tabela 1 ma kolumnę, do której chcesz dodać ograniczenie klucza obcego, ale wartości w foreign_key_id_column nie pasują do id w tabeli 2.
- początkowe select wyświetla identyfikatory z table1. będą to wiersze, które chcemy usunąć.
- klauzula "not in" w instrukcji where ogranicza zapytanie tylko do wierszy, w których wartość w foreign_key_id_column nie znajduje się na liście identyfikatorów tabeli 2.
- instrukcja select w nawiasie otrzyma lista wszystkich identyfikatorów znajdujących się w tabeli 2.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-31 17:36:39
Gdzie T2
jest tabelą, do której dodajesz ograniczenie:
SELECT *
FROM T2
WHERE constrain_field NOT
IN (
SELECT DISTINCT t.constrain_field
FROM T2
INNER JOIN T1 t
USING ( constrain_field )
)
I usunąć wyniki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 18:41:44
Niech mamy następujące 2 tabele (wynagrodzenie i pracownik)
Teraz chcę te dane z tabeli pracowników, które nie są w pensji. Możemy to zrobić na 3 sposoby -
-
Korzystanie z połączenia wewnętrznego
Select * from employee where id not in (select e.id od pracownika e wewnętrzne Dołącz wynagrodzenie s na e.id=s.id)
-
Korzystanie z LEFT outer join
Select * from employee e left outer join pensja s na e.id=s.id gdzie s.id is null
-
Korzystanie Z Pełnego Połączenia
Select * from employee e full outer join pensja s on e.id=s.id gdzie e.id Nie w (Wybierz id z pensji)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-14 15:32:55
Nie wiedziałem, który jest zoptymalizowany (w porównaniu do @AdaTheDev ) ale ten wydaje się być szybszy, gdy używam (przynajmniej dla mnie)
SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2
Jeśli chcesz uzyskać inny konkretny atrybut, możesz użyć:
SELECT COUNT(*) FROM table_1 where id in (SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 06:59:38
Jak wybrać wiersze bez pasującego wpisu w obu tabelach?
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-06 05:45:55