Frage

Ich habe zwei Tabellen, die miteinander verbunden sind.

A hat viele B

Normalerweise würden Sie tun:

select * from a,b where b.a_id = a.id

Um alle Datensätze aus einer zu erhalten, die einen Datensatz in b hat.

Wie kann ich in einem nur die Datensätze erhalten, dass nichts in b hat?

War es hilfreich?

Lösung

select * from a where id not in (select a_id from b)

Oder wie einige andere Leute auf diesen Thread sagt:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null

Andere Tipps

select * from a
left outer join b on a.id = b.a_id
where b.a_id is null

Ein weiterer Ansatz:

select * from a where not exists (select * from b where b.a_id = a.id)

Die „existiert“ Ansatz nützlich ist, wenn es eine andere „where“ -Klausel ist müssen Sie die innere Abfrage befestigen.

SELECT id FROM a
EXCEPT
SELECT a_id FROM b;

select * from a where id nicht in (wählen a_id aus b)

Sie werden wahrscheinlich viel bessere Leistung (als mit ‚nicht in‘), wenn Sie eine äußere Verwendung kommen:

select * from a left outer join b on a.id = b.a_id where b.a_id is null;

Dadurch werden Sie von Nullen in der IN-Klausel schützen, die zu unerwartetem Verhalten führen kann.

select * from einer where id nicht in (wählen Sie [eine id] aus b wobei [a id] nicht null )

Bei einem kommen, es ist ziemlich schnell, aber wenn wir Datensätze aus Datenbank zu entfernen, die etwa 50 milions Aufzeichnungen haben und 4 und mehr schließt sich aufgrund von Fremdschlüsseln, es dauert ein paar Minuten, es zu tun. Viel schneller zu verwenden, wenn nicht in einem Zustand wie folgt aus:

select a.* from a
where a.id NOT IN(SELECT DISTINCT a_id FROM b where a_id IS NOT NULL)
//And for more joins
AND a.id NOT IN(SELECT DISTINCT a_id FROM c where a_id IS NOT NULL)

Ich kann diesen Ansatz auch empfohlen, falls zum Löschen wir haben nicht konfiguriert Kaskade löschen. Diese Abfrage dauert nur wenige Sekunden.

Der erste Ansatz ist

select a.* from a where a.id  not in (select b.ida from b)

Der zweite Ansatz ist

select a.*
  from a left outer join b on a.id = b.ida
  where b.ida is null

Der erste Ansatz ist sehr teuer. Der zweite Ansatz ist besser.

Mit PostgreSql 9.4, ich habe die "erklären Abfrage" -Funktion und die erste Abfrage als Kosten von cost = 0.00..1982043603.32 . Stattdessen wird die Join-Abfrage als Kosten von cost = 45946.77..45946.78

Zum Beispiel, Ich suche für alle Produkte, die ohne Fahrzeuge, die nicht kompatibel sind. Ich habe 100k Produkte und mehr als 1 m Kompatibilitäten.

select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null

Die Join-Abfrage verbrachte etwa 5 Sekunden lang, anstatt die Unterabfrage Version nach 3 Minuten nie beendet wird.

Eine andere Art und Weise des Schreibens es

select a.*
from a 
left outer join b
on a.id = b.id
where b.id is null

Ouch, geschlagen von Nathan:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top