Szukaj…


Wprowadzenie

W Structured Query Language (SQL) JOIN to metoda łączenia dwóch tabel danych w jednym zapytaniu, umożliwiająca bazie danych zwrócenie zestawu zawierającego dane z obu tabel jednocześnie lub użycie danych z jednej tabeli do użycia jako Filtruj na drugim stole. Istnieje kilka rodzajów JOIN zdefiniowanych w standardzie ANSI SQL.

Przyłączenie wewnętrzne

Inner join zwraca tylko te rekordy / wiersze, które pasują / istnieją w obu tabelach na podstawie jednego lub więcej warunków (określonych za pomocą słowa kluczowego ON ). Jest to najczęstszy rodzaj łączenia. Ogólna składnia inner join jest następująca:

SELECT * 
FROM table_1
INNER JOIN table_2
  ON table_1.column_name = table_2.column_name

Można to również uprościć, JOIN :

SELECT * 
FROM table_1
JOIN table_2
  ON table_1.column_name = table_2.column_name

Przykład

/* Sample data. */
DECLARE @Animal table (
    AnimalId Int IDENTITY,
    Animal Varchar(20)
);

DECLARE @AnimalSound table (
    AnimalSoundId Int IDENTITY,
    AnimalId Int,
    Sound Varchar(20)
);

INSERT INTO @Animal (Animal) VALUES ('Dog');
INSERT INTO @Animal (Animal) VALUES ('Cat');
INSERT INTO @Animal (Animal) VALUES ('Elephant');

INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (1, 'Barks');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (2, 'Meows');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (3, 'Trumpets');
/* Sample data prepared. */

SELECT 
    * 
FROM 
    @Animal
    JOIN @AnimalSound
        ON @Animal.AnimalId = @AnimalSound.AnimalId;
AnimalId    Animal               AnimalSoundId AnimalId    Sound
----------- -------------------- ------------- ----------- --------------------
1           Dog                  1             1           Barks
2           Cat                  2             2           Meows
3           Elephant             3             3           Trumpets

Używanie złączenia wewnętrznego z lewym łączeniem zewnętrznym (Zastępowanie nie istnieje)

To zapytanie zwróci dane z tabeli 1, gdzie pola pasujące do tabeli 2 z kluczem i dane nie w tabeli 1, w porównaniu z tabelą 2 z warunkiem i kluczem

select * 
  from Table1 t1
    inner join Table2 t2 on t1.ID_Column = t2.ID_Column 
    left  join Table3 t3 on t1.ID_Column = t3.ID_Column 
  where t2.column_name = column_value 
    and t3.ID_Column is null 
  order by t1.column_name;

Cross Join

A cross join jest A cross join kartezjańskim, co oznacza iloczyn kartezjański obu tabel. To połączenie nie wymaga żadnego warunku, aby połączyć dwie tabele. Każdy wiersz w lewej tabeli zostanie dołączony do każdego wiersza w prawej tabeli. Składnia dla połączenia krzyżowego:

SELECT * FROM table_1
CROSS JOIN table_2 

Przykład:

/* Sample data. */
DECLARE @Animal table (
    AnimalId Int IDENTITY,
    Animal Varchar(20)
);

DECLARE @AnimalSound table (
    AnimalSoundId Int IDENTITY,
    AnimalId Int,
    Sound Varchar(20)
);

INSERT INTO @Animal (Animal) VALUES ('Dog');
INSERT INTO @Animal (Animal) VALUES ('Cat');
INSERT INTO @Animal (Animal) VALUES ('Elephant');

INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (1, 'Barks');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (2, 'Meows');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (3, 'Trumpet');
/* Sample data prepared. */

SELECT 
    * 
FROM 
    @Animal 
    CROSS JOIN @AnimalSound;

Wyniki:

AnimalId    Animal               AnimalSoundId AnimalId    Sound
----------- -------------------- ------------- ----------- --------------------
1           Dog                  1             1           Barks
2           Cat                  1             1           Barks
3           Elephant             1             1           Barks
1           Dog                  2             2           Meows
2           Cat                  2             2           Meows
3           Elephant             2             2           Meows
1           Dog                  3             3           Trumpet
2           Cat                  3             3           Trumpet
3           Elephant             3             3           Trumpet

Należy pamiętać, że istnieją inne sposoby zastosowania połączenia krzyżowego. Jest to sprzężenie w „starym stylu” (przestarzałe od ANSI SQL-92) bez warunków, co powoduje sprzężenie krzyżowe / kartezjańskie:

SELECT * 
FROM @Animal, @AnimalSound;

Ta składnia działa również z powodu warunku „zawsze prawdziwego” łączenia, ale nie jest zalecana i należy jej unikać, na rzecz jawnej składni CROSS JOIN , ze względu na czytelność.

SELECT * 
FROM 
    @Animal 
    JOIN @AnimalSound 
        ON 1=1

Outer Join

Lewy zewnętrzny łącznik

LEFT JOIN zwraca wszystkie wiersze z lewej tabeli, dopasowane do wierszy z prawej tabeli, w których spełnione są warunki klauzuli ON . Wiersze, w których klauzula ON nie jest spełniona, mają NULL we wszystkich kolumnach prawej tabeli. Składnia LEFT JOIN to:

SELECT * FROM table_1 AS t1
LEFT JOIN table_2 AS t2 ON t1.ID_Column = t2.ID_Column 

Right Outer Join

RIGHT JOIN zwraca wszystkie wiersze z prawej tabeli, dopasowane do wierszy z lewej tabeli, w których spełnione są warunki klauzuli ON . Wiersze, w których klauzula ON nie jest spełniona, mają NULL we wszystkich kolumnach lewej tabeli. Składnia RIGHT JOIN jest następująca:

SELECT * FROM table_1 AS t1
RIGHT JOIN table_2 AS t2 ON t1.ID_Column = t2.ID_Column 

Pełne połączenie zewnętrzne

FULL JOIN łączy LEFT JOIN i RIGHT JOIN . Wszystkie wiersze są zwracane z obu tabel, niezależnie od tego, czy warunki w klauzuli ON są spełnione. Wiersze, które nie spełniają klauzuli ON , są zwracane z NULL we wszystkich przeciwnych kolumnach tabeli (to znaczy, dla wiersza w lewej tabeli wszystkie kolumny w prawej tabeli będą zawierać NULL i odwrotnie). Składnia FULL JOIN jest następująca:

SELECT * FROM table_1 AS t1
FULL JOIN table_2 AS t2 ON t1.ID_Column = t2.ID_Column  

Przykłady

/* Sample test data. */
DECLARE @Animal table (
    AnimalId Int IDENTITY,
    Animal Varchar(20)
);

DECLARE @AnimalSound table (
    AnimalSoundId Int IDENTITY,
    AnimalId Int,
    Sound Varchar(20)
);

INSERT INTO @Animal (Animal) VALUES ('Dog');
INSERT INTO @Animal (Animal) VALUES ('Cat');
INSERT INTO @Animal (Animal) VALUES ('Elephant');
INSERT INTO @Animal (Animal) VALUES ('Frog');

INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (1, 'Barks');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (2, 'Meows');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (3, 'Trumpet');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (5, 'Roars');
/* Sample data prepared. */

DOŁĄCZ DO LEWEGO ZEWNĘTRZNEGO

SELECT * 
FROM @Animal As t1 
LEFT JOIN @AnimalSound As t2 ON t1.AnimalId = t2.AnimalId;

Wyniki dla LEFT JOIN

AnimalId    Animal               AnimalSoundId AnimalId    Sound
----------- -------------------- ------------- ----------- --------------------
1           Dog                  1             1           Barks
2           Cat                  2             2           Meows
3           Elephant             3             3           Trumpet
4           Frog                 NULL          NULL        NULL

DOŁĄCZ DO PRAWEJ ZEWNĘTRZNEJ

SELECT * 
FROM @Animal As t1 
RIGHT JOIN @AnimalSound As t2 ON t1.AnimalId = t2.AnimalId;

Wyniki dla RIGHT JOIN

AnimalId    Animal               AnimalSoundId AnimalId    Sound
----------- -------------------- ------------- ----------- --------------------
1           Dog                  1             1           Barks
2           Cat                  2             2           Meows
3           Elephant             3             3           Trumpet
NULL        NULL                 4             5           Roars

DOŁĄCZ DO ZEWNĘTRZNEGO

SELECT * 
FROM @Animal As t1 
FULL JOIN @AnimalSound As t2 ON t1.AnimalId = t2.AnimalId;

Wyniki dla FULL JOIN

AnimalId    Animal               AnimalSoundId AnimalId    Sound
----------- -------------------- ------------- ----------- --------------------
1           Dog                  1             1           Barks
2           Cat                  2             2           Meows
3           Elephant             3             3           Trumpet
4           Frog                 NULL          NULL        NULL
NULL        NULL                 4             5           Roars

Korzystanie z dołączenia w aktualizacji

Połączenia mogą być również używane w instrukcji UPDATE :

CREATE TABLE Users (
    UserId int NOT NULL,
    AccountId int NOT NULL,
    RealName nvarchar(200) NOT NULL
)

CREATE TABLE Preferences (
    UserId int NOT NULL,
    SomeSetting bit NOT NULL
)

Zaktualizuj kolumnę SomeSetting filtrowania tabeli Preferences według predykatu w tabeli Users w następujący sposób:

UPDATE p
SET p.SomeSetting = 1
FROM Users u
JOIN Preferences p ON u.UserId = p.UserId
WHERE u.AccountId = 1234

p jest aliasem dla Preferences zdefiniowanych w klauzuli FROM instrukcji. AccountId będą tylko wiersze z pasującym AccountId z tabeli Users .

Zaktualizuj z lewymi zewnętrznymi instrukcjami łączenia

Update t 
SET  t.Column1=100
FROM Table1 t LEFT JOIN Table12 t2 
ON t2.ID=t.ID

Aktualizuj tabele z wewnętrznym połączeniem i funkcją agregującą

UPDATE t1
SET t1.field1 = t2.field2Sum
FROM table1 t1
INNER JOIN (select field3, sum(field2) as field2Sum
from table2
group by field3) as t2
on t2.field3 = t1.field3  

Dołącz do podzapytania

Dołączanie do podzapytania jest często używane, gdy chcesz uzyskać dane zagregowane (takie jak Liczba, Śr., Maks. Lub Min.) Z tabeli podrzędnej / szczegółów i wyświetlić ją wraz z rekordami z tabeli nadrzędnej / nagłówka. Na przykład możesz chcieć pobrać górny / pierwszy wiersz podrzędny na podstawie daty lub identyfikatora, a może chcesz liczbę wszystkich wierszy podrzędnych lub średnią.

W tym przykładzie użyto aliasów, które ułatwiają odczytywanie zapytań, gdy w grę wchodzi wiele tabel. W tym przypadku pobieramy wszystkie wiersze z tabeli nadrzędnej Zamówienia zakupu i pobieramy tylko ostatni (lub najnowszy) wiersz podrzędny z tabeli podrzędnej PurchaseOrderLineItems. W tym przykładzie założono, że tabela potomna używa przyrostowych identyfikatorów numerycznych.

SELECT po.Id, po.PODate, po.VendorName, po.Status, item.ItemNo, 
  item.Description, item.Cost, item.Price
FROM PurchaseOrders po
LEFT JOIN 
     (
       SELECT l.PurchaseOrderId, l.ItemNo, l.Description, l.Cost, l.Price, Max(l.id) as Id 
       FROM PurchaseOrderLineItems l
       GROUP BY l.PurchaseOrderId, l.ItemNo, l.Description, l.Cost, l.Price
     ) AS item ON item.PurchaseOrderId = po.Id

Self Join

Tabelę można łączyć ze sobą w tak zwane samo łączenie, łącząc rekordy w tabeli z innymi rekordami w tej samej tabeli. Połączenia automatyczne są zwykle używane w zapytaniach, w których zdefiniowana jest hierarchia w kolumnach tabeli.

Rozważ przykładowe dane w tabeli o nazwie Employees :

ID Nazwa Boss_ID
1 Kok 3)
2) Jim 1
3) Sam 2)

Boss_ID każdego pracownika odwzorowuje na ID innego pracownika. Aby pobrać listę pracowników z nazwiskiem ich szefa, tabelę można połączyć na sobie za pomocą tego mapowania. Zauważ, że dołączenie do tabeli w ten sposób wymaga użycia aliasu (w tym przypadku Bosses ) w drugim odwołaniu do tabeli, aby odróżnić się od oryginalnej tabeli.

SELECT Employees.Name,
    Bosses.Name AS Boss
FROM Employees
INNER JOIN Employees AS Bosses 
    ON Employees.Boss_ID = Bosses.ID

Wykonanie tego zapytania spowoduje wyświetlenie następujących wyników:

Nazwa Szef
Kok Sam
Jim Kok
Sam Jim

Usuń za pomocą Dołącz

Złączeń można także używać w instrukcji DELETE . Biorąc pod uwagę następujący schemat:

CREATE TABLE Users (
    UserId int NOT NULL,
    AccountId int NOT NULL,
    RealName nvarchar(200) NOT NULL
)

CREATE TABLE Preferences (
    UserId int NOT NULL,
    SomeSetting bit NOT NULL
)

Możemy usunąć wiersze z tabeli Preferences , filtrując według predykatu z tabeli Users w następujący sposób:

DELETE p
FROM Users u
INNER JOIN Preferences p ON u.UserId = p.UserId
WHERE u.AccountId = 1234

Tutaj p jest aliasem dla Preferences zdefiniowanych w klauzuli FROM instrukcji i usuwamy tylko te wiersze, które mają pasujące AccountId z tabeli Users .

Przypadkowe przekształcenie złącza zewnętrznego w złącze wewnętrzne

Sprzężenia zewnętrzne zwracają wszystkie wiersze z jednej lub obu tabel oraz pasujące wiersze.

Table People
PersonID FirstName
       1 Alice
       2 Bob
       3 Eve

Table Scores
PersonID Subject Score
       1 Math    100
       2 Math     54
       2 Science  98

Lewe dołączanie do tabel:

Select * from People a
left join Scores b
on a.PersonID = b.PersonID

Zwroty:

PersonID FirstName PersonID Subject Score
       1 Alice            1 Math    100
       2 Bob              2 Math     54
       2 Bob              2 Science  98
       3 Eve           NULL NULL   NULL

Jeśli chciałbyś zwrócić wszystkie osoby, z odpowiednimi wynikami matematycznymi, częstym błędem jest napisanie:

Select * from People a
left join Scores b
on a.PersonID = b.PersonID
where Subject = 'Math'

Spowoduje to usunięcie Ewy z twoich wyników, oprócz usunięcia wyniku naukowego Boba, ponieważ Subject jest dla niej NULL .

Prawidłowa składnia do usuwania rekordów innych niż matematyczne przy jednoczesnym zachowaniu wszystkich osób w tabeli People to:

Select * from People a
left join Scores b
on a.PersonID = b.PersonID
and b.Subject = 'Math'


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow