2008-12-15 4 views
226

ich die folgenden zwei SQL-Tabellen haben (in MySQL):SQL - finden Datensätze aus einer Tabelle, die in einem anderen nicht existieren

Phone_book 
+----+------+--------------+ 
| id | name | phone_number | 
+----+------+--------------+ 
| 1 | John | 111111111111 | 
+----+------+--------------+ 
| 2 | Jane | 222222222222 | 
+----+------+--------------+ 

Call 
+----+------+--------------+ 
| id | date | phone_number | 
+----+------+--------------+ 
| 1 | 0945 | 111111111111 | 
+----+------+--------------+ 
| 2 | 0950 | 222222222222 | 
+----+------+--------------+ 
| 3 | 1045 | 333333333333 | 
+----+------+--------------+ 

Wie finde ich heraus, die von Menschen gemacht wurden Anrufe, deren phone_number ist nicht in der Phone_book? Die gewünschte Ausgabe wäre:

Jede Hilfe würde sehr geschätzt werden.

Antwort

307

Es gibt verschiedene Möglichkeiten, dies zu tun, mit unterschiedlicher Effizienz, je nachdem, wie gut Ihre Abfrage-Optimierer ist, und die relative Größe der beiden Tabellen:

Dies ist die kürzeste Erklärung und kann schnellste sein, wenn Ihr Telefonbuch ist sehr kurz:

SELECT * 
FROM Call 
WHERE phone_number NOT IN (SELECT phone_number FROM Phone_book) 

alternativ (dank Alterlife)

SELECT * 
FROM Call 
WHERE NOT EXISTS 
    (SELECT * 
    FROM Phone_book 
    WHERE Phone_book.phone_number = Call.phone_number) 

oder (dank WOPR)

SELECT * 
FROM Call 
LEFT OUTER JOIN Phone_Book 
    ON (Call.phone_number = Phone_book.phone_number) 
    WHERE Phone_book.phone_number IS NULL 

(das zu ignorieren, wie andere gesagt haben, ist es normalerweise am besten, nur die Spalten auswählen, die Sie wollen, nicht ‚*‘)

+1

vermeiden, benutze VORHANDEN - der Hinweis in der Frage Titel ist – annakata

+16

Die linke äußere Verknüpfung wird wahrscheinlich im allgemeinen Fall schnellste wie es die Ausführung der wiederholt verhindert Unterabfrage – WOPR

+0

Nicht wählerisch, aber die Unterabfrage auf meinem Vorschlag gibt select 'x' und nicht select * zurück – Alterlife

17

Der Code unten ein wenig effizienter als die Antworten oben dargestellt würde bei größeren Datensätzen.

SELECT * FROM Call WHERE 
NOT EXISTS (SELECT 'x' FROM Phone_book where 
Phone_book.phone_number = Call.phone_number) 
+1

Wie immer lohnt es sich, die Leistung der Abfragen für das Ziel-Dataset zu profilieren, um das mit der besten Leistung auszuwählen. SQL-Optimierer sind in diesen Tagen gut genug, dass die Leistungsergebnisse oft überraschend sind. –

59
SELECT Call.ID, Call.date, Call.phone_number 
FROM Call 
LEFT OUTER JOIN Phone_Book 
    ON (Call.phone_number=Phone_book.phone_number) 
    WHERE Phone_book.phone_number IS NULL 

Sollte die Unterabfrage entfernen, so dass die Abfrage-Optimierer seine Magie arbeiten.

Vermeiden Sie auch "SELECT *", weil es Ihren Code brechen kann, wenn jemand die zugrunde liegenden Tabellen oder Sichten ändert (und es ist ineffizient).

+6

Dies ist im Allgemeinen die effizienteste Methode, da es keine Mehrfachdurchgänge auf der zweiten Tabelle durchführt ... hoffe, dass einige Leute die Kommentare lesen. – Nerdfest

+2

Ich würde lieber hoffen, dass Menschen Profil: Wenn Sie nicht ein Top-SQL-Performance-Guru, im Voraus sagen, was der schnellste sein wird, ist ziemlich schwierig (und hängt von der DBMS-Engine, die Sie verwenden). – bortzmeyer

+1

Die große O-Notation wird Ihnen leicht sagen, was Sie in diesem Fall am schnellsten erwarten können. Es ist um Größenordnungen anders. – Jonesopolis

4

Ich denke

SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON 
CALL.id = Phone_book.id WHERE Phone_book.name IS NULL 
+0

Die ID-Spalte in der Call-Tabelle hat nicht den gleichen Wert wie die ID-Spalte in der Tabelle Phone_book. Sie können also nicht an diesen Werten teilnehmen. Siehe die WOPR-Antwort für einen ähnlichen Ansatz. –

3
SELECT DISTINCT Call.id 
FROM Call 
LEFT OUTER JOIN Phone_book USING (id) 
WHERE Phone_book.id IS NULL 

Dies wird die zusätzliche ID-s zurück, die in Ihrer phone_book Tabelle fehlen.

1
SELECT t1.ColumnID, 
CASE 
    WHEN NOT EXISTS(SELECT t2.FieldText 
        FROM Table t2 
        WHERE t2.ColumnID = t1.ColumnID) 
    THEN t1.FieldText 
    ELSE t2.FieldText 
END FieldText  
FROM Table1 t1, Table2 t2 
+0

Dies wird Ihnen Daten aus einer Tabelle zurückgeben, wenn Daten in einer anderen Tabelle für die gleiche Spalte nicht vorhanden sind –

+0

Könnten Sie auch eine Erklärung hinzufügen, was das löst? –

1
SELECT name, phone_number FROM Call a 
WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b) 
+0

Dies bietet keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag. - [Aus Bewertung] (/ review/low-quality-posts/10501884) –

+0

@DennisKriechel aktualisierte Abfrage, so dass es spezifischer für die Frage ist. – JoshYates1980

0

Alternativ

select id from call 
minus 
select id from phone_number 
+1

Nicht sicher, dass dies die Frage so beantwortet, wie es ist (obwohl der Operator MINUS) eine neue Ergänzung ist. Dies endete in der Warteschlange mit niedriger Qualität - Sie könnten diese Antwort gerne verbessern. –

Verwandte Themen