2010-11-12 7 views
5

Ich habe zwei Tabellen A und B. A ist das Elternteil von B. Ich versuche, alle As zu finden, die kein bestimmtes B als Kind haben. Normalerweise würde ichSQL Auswahl von Zeilen und Ausschluss von Kindern

SELECT A.id FROM A 
    WHERE A.id NOT IN 
     (SELECT B.AId FROM B WHERE B.someFK = foo);

jedoch aus Leistungsgründen ich daran interessiert bin nicht eine innere wählen zu verwenden. Ich habe versucht, so etwas wie:

SELECT A.id FROM A 
    LEFT JOIN B ON (A.id = B.AId) 
    WHERE B.someFK != foo OR B.someFK IS NULL

Das Problem ist, diese wieder als der mehr als ein Kind hat, unabhängig davon, ob sie die angegebene B.

EDIT: B.id nach B geändert someFK

+0

Whoops, dachte nicht, dass es einen Unterschied machen würde, aber B.id sollte B.someFK sein. Das bedeutet, dass As das ausgeschlossene Foo teilen kann. – Jim

+0

sollten Sie das wahrscheinlich direkt in der Frage bearbeiten, damit es für neue Leser bemerkenswerter ist. – DMA57361

+0

Sie sind neu in StackOverflow. Bitte akzeptiere eine Antwort, wenn dein Problem gelöst wurde. – Falcon

Antwort

1

ich gehen würde, mit der Klausel existiert, da es für einen solchen Zweck gemacht wurde:

SELECT A.id FROM A WHERE NOT EXISTS (SELECT 1 FROM B WHERE B.id = foo and B.AId=a.id); 

In den meisten Datenbanken ist es viel leistungsfähiger als die in Klausel (die im Grunde ist ein Array zu vergleichen) für große Datensätze.

Aggregationen sind auch teuer, so mit einer exists Anweisung ist der Weg zu gehen imho. Sie könnten jedoch Aggregationen für Ihr Szenario versuchen.

0

Versuchen Sie, eine MAX-Einschränkung für Ihre Elterntabelle zu verwenden. Ich habe MySql eine Weile nicht benutzt, aber das sollte Ihnen die Idee

1

Ihr LEFT JOIN wird für jeden A eine Zeile zurückgeben - B Link (oder eine Zeile für ein A ohne Verbindung zu B) und entfernt dann die Links, die Ihre Kriterien nicht entsprechen - hinter jedem anderen Link verlassen, dass ein bestimmten A hat in B, was nicht das ist, was Sie wollen.

Allerdings denke ich eine innere Auswahl ist notwendig.
Aber vielleicht ein EXISTS stattdessen versuchen:

SELECT A.id 
FROM A 
WHERE NOT EXISTS (SELECT * FROM B WHERE B.AId = A.id AND B.someFK = foo); 
0

Versuchen Sie, diese

SELECT DISTINCT A.id FROM A 
LEFT JOIN B ON (A.id = B.AId) 
WHERE B.id != foo OR B.id IS NULL 
+0

Performance-weise eine schlechte Wahl, mit Join und distinct. – Falcon

0

Sie sollten die gesamten Kriterien in der LEFT JOIN setzen.

Soweit die doppelten Zeilen betroffen sind, einfach DISTINCT es.

Verwandte Themen