it-swarm.com.de

SQL - Wie gibt man Zeilen aus der linken Tabelle zurück, die nicht in der rechten Tabelle gefunden wurden?

Ich habe zwei Tabellen mit ähnlichen Spaltennamen und muss Datensätze aus der linken Tabelle zurückgeben, die nicht in der rechten Tabelle gefunden werden. Ich habe einen Primärschlüssel (Spalte), der mir hilft, beide Tabellen zu vergleichen. Welcher Join wird bevorzugt?

35
CloudJedi

Wenn Sie nach T-SQL fragen, wollen wir uns zuerst mit den Grundlagen befassen. Es gibt drei Arten von Verknüpfungen, von denen jede ihre eigenen logischen Verarbeitungsphasen hat:

  1. Ein cross join ist am einfachsten. Es implementiert nur eine logische Abfrageverarbeitungsphase, Cartesian Product. Diese Phase arbeitet an den beiden Tabellen, die als Eingabe für die Verknüpfung bereitgestellt werden, und erzeugt ein kartesisches Produkt aus den beiden. Das heißt, jede Zeile einer Eingabe wird mit allen Zeilen der anderen übereinstimmen. Wenn Sie also m Zeilen in einer Tabelle und n Zeilen in der anderen Tabelle haben, erhalten Sie im Ergebnis m × n Zeilen.
  2. Dann sind Inner joins: Sie wenden zwei logische Abfrageverarbeitungsphasen an: A Cartesian product zwischen den beiden Eingabetabellen wie bei einem Cross-Join und dann filters Zeilen, die auf einem Prädikat basieren, das Sie in der ON-Klausel (auch als Join condition angegeben) angeben.
  3. Als nächstes kommt der dritte Typ von Joins, Outer Joins:

    In einem outer join markieren Sie eine Tabelle als preserved-Tabelle, indem Sie die Schlüsselwörter LEFT OUTER JOIN, RIGHT OUTER JOIN oder FULL OUTER JOIN zwischen den Tabellennamen verwenden. Das Schlüsselwort OUTER lautet optional. Das Schlüsselwort LEFT bedeutet, dass die Zeilen von left table beibehalten werden. Das Schlüsselwort RIGHT bedeutet, dass die Zeilen in right table beibehalten werden. und das Schlüsselwort FULL bedeutet, dass die Zeilen in den Tabellen both, left und right beibehalten werden.

    Die dritte logische Abfrageverarbeitungsphase eines outer join identifiziert die Zeilen aus der beibehaltenen Tabelle, die keine Übereinstimmungen in der anderen Tabelle gefunden haben, basierend auf dem Prädikat ON. In dieser Phase werden diese Zeilen der Ergebnistabelle hinzugefügt, die von den ersten beiden Phasen des Joins erzeugt wird, und NULL-Markierungen als Platzhalter für die Attribute von der nicht konservierten Seite des Joins in diesen äußeren Zeilen.

Wenn wir uns nun die Frage ansehen: Um Datensätze aus der linken Tabelle zurückzugeben, die nicht in der rechten Tabelle enthalten sind, verwenden Sie Left outer join und filtern die Zeilen mit NULL-Werten für die Attribute von der rechten Seite des Joins.

32
Deepshikha

Versuche dies

SELECT f.*
FROM first_table f LEFT JOIN second_table s ON f.key=s.key
WHERE s.key is NULL

Weitere Informationen finden Sie in diesem Artikel: Joins in Sql Server

enter image description here

44
Shamseer K

Ich benutze auch gerne NOT EXISTS. Wenn es um die Leistung geht, sollte der Index einen LEFT JOIN oder besser ausführen. Außerdem ist es einfacher zu lesen.

SELECT Column1
FROM TableA a
WHERE NOT EXISTS ( SELECT Column1
                   FROM Tableb b
                   WHERE a.Column1 = b.Column1
                 )
4
viejoEngineer

Ich kann den beiden anderen Antworten nur ein Codebeispiel hinzufügen: Ich finde es jedoch nützlich, es in Aktion zu sehen (die anderen Antworten sind meiner Meinung nach besser, weil sie es erklären). 

DECLARE @testLeft TABLE (ID INT, SomeValue VARCHAR(1))
DECLARE @testRight TABLE (ID INT, SomeOtherValue VARCHAR(1))

INSERT INTO @testLeft (ID, SomeValue) VALUES (1, 'A')
INSERT INTO @testLeft (ID, SomeValue) VALUES (2, 'B')
INSERT INTO @testLeft (ID, SomeValue) VALUES (3, 'C')


INSERT INTO @testRight (ID, SomeOtherValue) VALUES (1, 'X')
INSERT INTO @testRight (ID, SomeOtherValue) VALUES (3, 'Z')

SELECT l.*
FROM 
    @testLeft l
     LEFT JOIN 
    @testRight r ON 
        l.ID = r.ID
WHERE r.ID IS NULL 
2
AHiggins

Diese Seite enthält eine Übersicht der verschiedenen Join-Typen sowie Visualisierungen von Venn-Diagrammen, die helfen sollen, den Unterschied in den Joins zu visualisieren.

Wie in den Kommentaren gesagt, ist dies eine recht grundlegende Frage nach den Klängen, daher sollten Sie versuchen, die Unterschiede zwischen den Joins und deren Bedeutung zu verstehen.

Check out http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/

Sie suchen nach einer Suchanfrage wie:

DECLARE @table1 TABLE (test int)
DECLARE @table2 TABLE (test int)

INSERT INTO @table1
(
    test
)
SELECT 1
UNION ALL SELECT 2

INSERT INTO @table2
(
    test
)
SELECT 1
UNION ALL SELECT 3

-- Here's the important part
SELECT  a.*
FROM    @table1 a
LEFT    join @table2 b on a.test = b.test -- this will return all rows from a
WHERE   b.test IS null -- this then excludes that which exist in both a and b

-- Returned results:

2
1
Kritner

wählen Sie * aus der linken Tabelle aus, wo sich das Schlüsselfeld nicht befindet (wählen Sie das Schlüsselfeld aus der rechten Tabelle aus)

0
George Let

Dies ist ein Beispiel aus der Praxis. Ich wurde gebeten, eine Liste der Benutzer anzugeben, die in den letzten 6 Monaten auf unserer Website gekauft haben, jedoch nicht in den letzten 3 Monaten.

Der verständlichste Weg, den ich mir vorstellen kann, ist für mich wie folgt:

--Users that bought from us 6 months ago and between 3 months ago.
DECLARE @6To3MonthsUsers table (UserID int,OrderDate datetime)
INSERT @6To3MonthsUsers
    select u.ID,opd.OrderDate
        from OrdersPaid opd
        inner join Orders o
        on opd.OrderID = o.ID
        inner join Users u
        on o.BuyerID = u.ID
        where 1=1 
        and opd.OrderDate BETWEEN DATEADD(m,-6,GETDATE()) and DATEADD(m,-3,GETDATE())

--Users that bought from us in the last 3 months
DECLARE @Last3MonthsUsers table (UserID int,OrderDate datetime)
INSERT @Last3MonthsUsers
    select u.ID,opd.OrderDate
        from OrdersPaid opd
        inner join Orders o
        on opd.OrderID = o.ID
        inner join Users u
        on o.BuyerID = u.ID
        where 1=1 
        and opd.OrderDate BETWEEN DATEADD(m,-3,GETDATE()) and GETDATE()

Mit diesen beiden Tabellen in der Hand muss ich nur die Benutzer aus der Tabelle @ 6To3MonthsUsers holen, die nicht in @ Last3MonthsUsers table liegen.

Es gibt zwei einfache Möglichkeiten, dies zu erreichen:

  1. Left Join verwenden:

    select distinct a.UserID
    from @6To3MonthsUsers a
    left join @Last3MonthsUsers b
    on a.UserID = b.UserID
    where b.UserID is null
    
  2. Nicht in:

    select distinct a.UserID
    from @6To3MonthsUsers a
    where a.UserID not in (select b.UserID from @Last3MonthsUsers b)
    

Beide Wege bringen mich zum gleichen Ergebnis, ich persönlich bevorzuge den zweiten Weg, weil er lesbarer ist.

0
Offir Pe'er