sql >> Databasteknik >  >> RDS >> Sqlserver

Tre bord går med andra än INNER JOIN

Ja, jag använder alla tre dessa JOIN, även om jag tenderar att hålla mig till att bara använda LEFT (OUTER) JOIN s istället för att blanda LEFT och RIGHT JOINs. Jag använder också FULL OUTER JOIN s och CROSS JOIN s.

Sammanfattningsvis en INNER JOIN begränsar resultatuppsättningen endast till de poster som uppfylls av JOIN-villkoret. Tänk på följande tabeller

EDIT: Jag har bytt namn på tabellnamnen och prefixet dem med @ så att tabellvariabler kan användas för alla som läser det här svaret och vill experimentera.

Om du också vill experimentera med detta i webbläsaren, jag har ställt in allt på SQL Fiddle också;

@Table1

id | name
---------
1  | One
2  | Two
3  | Three
4  | Four

@Table2

id | name
---------
1  | Partridge
2  | Turtle Doves
3  | French Hens
5  | Gold Rings

SQL-kod

DECLARE @Table1 TABLE (id INT PRIMARY KEY CLUSTERED, [name] VARCHAR(25))

INSERT INTO @Table1 VALUES(1, 'One');
INSERT INTO @Table1 VALUES(2, 'Two');
INSERT INTO @Table1 VALUES(3, 'Three');
INSERT INTO @Table1 VALUES(4, 'Four');

DECLARE @Table2 TABLE (id INT PRIMARY KEY CLUSTERED, [name] VARCHAR(25))

INSERT INTO @Table2 VALUES(1, 'Partridge');
INSERT INTO @Table2 VALUES(2, 'Turtle Doves');
INSERT INTO @Table2 VALUES(3, 'French Hens');
INSERT INTO @Table2 VALUES(5, 'Gold Rings');

En INNER JOIN SQL-sats, sammanfogad på id fältet

SELECT 
    t1.id,
    t1.name,
    t2.name
FROM
    @Table1 t1
INNER JOIN
    @Table2 t2
    ON 
        t1.id = t2.id

Resultat i

id | name | name
----------------
1  | One  | Partridge
2  | Two  | Turtle Doves
3  | Three| French Hens

En LEFT JOIN kommer att returnera en resultatuppsättning med alla poster från tabellen på vänster sida av joinen (om du skulle skriva ut påståendet som en rad, tabellen som visas först) och fält från tabellen på höger sida av joinen som matchar join-uttrycket och ingår i SELECT klausul. Saknas detaljer kommer att fyllas i med NULL

SELECT 
    t1.id,
    t1.name,
    t2.name
FROM
    @Table1 t1
LEFT JOIN
    @Table2 t2
    ON 
        t1.id = t2.id

Resultat i

id | name | name
----------------
1  | One  | Partridge
2  | Two  | Turtle Doves
3  | Three| French Hens
4  | Four | NULL

En RIGHT JOIN är samma logik som en LEFT JOIN men kommer att returnera alla poster från den högra sidan av joinen och fält från den vänstra sidan som matchar join-uttrycket och som ingår i SELECT klausul.

SELECT 
    t1.id,
    t1.name,
    t2.name
FROM
    @Table1 t1
RIGHT JOIN
    @Table2 t2
    ON 
        t1.id = t2.id

Resultat i

id | name | name
----------------
1  | One  | Partridge
2  | Two  | Turtle Doves
3  | Three| French Hens
NULL| NULL| Gold Rings

Naturligtvis finns det också FULL OUTER JOIN , som inkluderar poster från båda sammanfogade tabeller och fyller i alla saknade detaljer med NULL.

SELECT 
    t1.id,
    t1.name,
    t2.name
FROM
    @Table1 t1
FULL OUTER JOIN
    @Table2 t2
    ON 
        t1.id = t2.id

Resultat i

id | name | name
----------------
1  | One  | Partridge
2  | Two  | Turtle Doves
3  | Three| French Hens
4  | Four | NULL
NULL| NULL| Gold Rings

Och en CROSS JOIN (även känd som en CARTESIAN PRODUCT ), som helt enkelt är produkten av korstillämpning av fält i SELECT uttalande från en tabell med fälten i SELECT uttalande från den andra tabellen. Lägg märke till att det inte finns något join-uttryck i en CROSS JOIN

SELECT 
    t1.id,
    t1.name,
    t2.name
FROM
    @Table1 t1
CROSS JOIN
    @Table2 t2

Resultat i

id | name  | name
------------------
1  | One   | Partridge
2  | Two   | Partridge
3  | Three | Partridge
4  | Four  | Partridge
1  | One   | Turtle Doves
2  | Two   | Turtle Doves
3  | Three | Turtle Doves
4  | Four  | Turtle Doves
1  | One   | French Hens
2  | Two   | French Hens
3  | Three | French Hens
4  | Four  | French Hens
1  | One   | Gold Rings
2  | Two   | Gold Rings
3  | Three | Gold Rings
4  | Four  | Gold Rings

EDIT:

Föreställ dig att det nu finns en Tabell3

@Table3

id | name
---------
2  | Prime 1
3  | Prime 2
5  | Prime 3

SQL-koden

DECLARE @Table3 TABLE (id INT PRIMARY KEY CLUSTERED, [name] VARCHAR(25))

INSERT INTO @Table3 VALUES(2, 'Prime 1');
INSERT INTO @Table3 VALUES(3, 'Prime 2');
INSERT INTO @Table3 VALUES(5, 'Prime 3');

Nu gick alla tre tabellerna med INNER JOINS

SELECT 
    t1.id,
    t1.name,
    t2.name,
    t3.name
FROM
    @Table1 t1
INNER JOIN
    @Table2 t2
    ON 
        t1.id = t2.id
INNER JOIN
    @Table3 t3
    ON 
        t1.id = t3.id

Resultat i

id | name | name         | name
-------------------------------
2  | Two  | Turtle Doves | Prime 1
3  | Three| French Hens  | Prime 2

Det kan hjälpa att förstå detta resultat genom att tro att poster med id 2 och 3 är de enda som är gemensamma för alla tre tabellerna och är också fältet vi går med i varje bord på.

Nu alla tre med LEFT JOINS

SELECT 
    t1.id,
    t1.name,
    t2.name,
    t3.name
FROM
    @Table1 t1
LEFT JOIN
    @Table2 t2
    ON 
        t1.id = t2.id
LEFT JOIN
    @Table3 t3
    ON 
        t1.id = t3.id

Resultat i

id | name | name         | name
-------------------------------
1  | One  | Partridge    | NULL
2  | Two  | Turtle Doves | Prime 1
3  | Three| French Hens  | Prime 2
4  | Four | NULL         | NULL

Joels svar är en bra förklaring för att förklara denna resultatuppsättning (Tabell 1 är bas-/ursprungstabellen).

Nu med en INNER JOIN och en LEFT JOIN

SELECT 
    t1.id,
    t1.name,
    t2.name,
    t3.name
FROM
    @Table1 t1
INNER JOIN
    @Table2 t2
    ON 
        t1.id = t2.id
LEFT JOIN
    @Table3 t3
    ON 
        t1.id = t3.id

Resultat i

id | name | name         | name
-------------------------------
1  | One  | Partridge    | NULL
2  | Two  | Turtle Doves | Prime 1
3  | Three| French Hens  | Prime 2

Även om vi inte vet i vilken ordning frågeoptimeraren kommer att utföra operationerna, kommer vi att titta på den här frågan uppifrån och ned för att förstå resultatuppsättningen. INNER JOIN på ids mellan Tabell1 och Tabell2 begränsar resultatuppsättningen till endast de poster som är uppfyllda av kopplingsvillkoret, dvs. de tre raderna som vi såg i det allra första exemplet. Denna tillfälliga resultatuppsättningen blir då LEFT JOIN ed till tabell 3 om id mellan tabell 1 och tabeller; Det finns poster i Tabell3 med id 2 och 3, men inte id 1, så fältet t3.name kommer att ha detaljer för 2 och 3 men inte 1.



  1. Hur man beräknar procentandelen av två kolumner i MySQL

  2. Bestående UUID i PostgreSQL med JPA

  3. NLS_NUMERIC_CHARACTERS inställning för decimal

  4. Hur man installerar SQL Server på SUSE 12