Wyjaśnienie łączeń własnych

84

Nie rozumiem potrzeby łączenia się przez siebie. Czy ktoś może mi je wyjaśnić?

Prosty przykład byłby bardzo pomocny.

Alex Gordon
źródło

Odpowiedzi:

95

Samosprzężenie można wyświetlić jako dwie identyczne tabele. Ale w normalizacji nie możesz utworzyć dwóch kopii tabeli, więc po prostu zasymuluj posiadanie dwóch tabel z samosprzężeniem.

Załóżmy, że masz dwie tabele:

Stół emp1

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

Stół emp2

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

Teraz, jeśli chcesz uzyskać nazwisko każdego pracownika wraz z nazwiskami jego szefa:

select c1.Name , c2.Name As Boss
from emp1 c1
    inner join emp2 c2 on c1.Boss_id = c2.Id

Który wyświetli następującą tabelę:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF
bezsensowna polityka
źródło
1
W tym przykładzie nie mogę dowiedzieć się, kto jest szefem. Chociaż exp jest dobry i łatwy do zrozumienia.
MAC
2
left joinMyślę, że lepiej byłoby nie pomijać pracownika (lub szefa), który nie ma szefa; najlepszy pies!
Rockin4Life33
22

Jest to dość powszechne, gdy masz tabelę, która odwołuje się do siebie. Przykład: tabela pracowników, w której każdy pracownik może mieć menedżera, a chcesz wyświetlić wszystkich pracowników i nazwisko ich kierownika.

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id
windyjonas
źródło
18

Łączenie własne to łączenie tabeli ze sobą.

Typowym przypadkiem użycia jest sytuacja, gdy tabela przechowuje jednostki (rekordy), które mają między sobą relację hierarchiczną . Na przykład tabela zawierająca informacje o osobie (imię i nazwisko, data urodzenia, adres ...) oraz kolumna zawierająca identyfikator ojca (i / lub matki). Następnie z małym zapytaniem, takim jak

SELECT Child.ID, Child.Name, Child.PhoneNumber, Father.Name, Father.PhoneNumber
FROM myTableOfPersons As Child
LEFT OUTER JOIN  myTableOfPersons As Father ON Child.FatherId = Father.ID
WHERE Child.City = 'Chicago'  -- Or some other condition or none

w tym samym zapytaniu możemy uzyskać informacje o dziecku i ojcu (i matce, z drugą osobą itp., a nawet o dziadkach itp.).

mjv
źródło
5

Powiedzmy, że masz stół users, ustawiony w ten sposób:

  • identyfikator użytkownika
  • Nazwa Użytkownika
  • identyfikator menedżera użytkownika

W tej sytuacji, jeśli chcesz wyciągnąć zarówno informacje o użytkowniku, jak i informacje o menedżerze w jednym zapytaniu, możesz zrobić to:

SELECT users.user_id, users.user_name, managers.user_id AS manager_id, managers.user_name AS manager_name INNER JOIN users AS manager ON users.manager_id=manager.user_id
ceejayoz
źródło
4

Są przydatne, jeśli Twój stół odwołuje się do siebie. Na przykład w przypadku tabeli stron każda strona może mieć łącze nexti previous. Będą to identyfikatory innych stron w tej samej tabeli. Jeśli w którymś momencie chcesz uzyskać trzy kolejne strony, zrób dwa samosprzężenia w kolumnach nexti previousz tą samą idkolumną tabeli .

Max Shawabkeh
źródło
4

Wyobraź sobie stół o nazwie Employeeopisanej poniżej. Wszyscy pracownicy mają menedżera, który jest również pracownikiem (może z wyjątkiem dyrektora generalnego, którego manager_id miałby wartość zero)

Table (Employee): 

int id,
varchar name,
int manager_id

Następnie możesz użyć poniższej opcji, aby znaleźć wszystkich pracowników i ich menedżerów:

select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id
Klaus Byskov Pedersen
źródło
4

Bez możliwości odniesienia się przez tabelę do samej siebie, musielibyśmy utworzyć tyle tabel dla poziomów hierarchii, ile jest warstw w hierarchii. Ale ponieważ ta funkcja jest dostępna, dołączasz stół do siebie, a sql traktuje go jako dwa oddzielne tabele, więc wszystko jest ładnie przechowywane w jednym miejscu.

Eugene
źródło
ale teraz (miejmy nadzieję) rozumiesz, co by się stało, gdyby samo odniesienie nie było dostępne.
Eugene
4

Oprócz odpowiedzi wymienionych powyżej (które są bardzo dobrze wyjaśnione), chciałbym dodać jeden przykład, aby można było łatwo pokazać użycie Self Join. Załóżmy, że masz tabelę o nazwie CUSTOMERS, która ma następujące atrybuty: CustomerID, CustomerName, ContactName, City, Country. Teraz chcesz wyświetlić listę wszystkich, którzy pochodzą z „tego samego miasta”. Będziesz musiał pomyśleć o replice tego stołu, abyśmy mogli do nich dołączyć na podstawie CITY. Poniższe zapytanie jasno pokaże, co to znaczy:

SELECT A.CustomerName AS CustomerName1, B.CustomerName AS CustomerName2, 
A.City
FROM Customers A, Customers B
WHERE A.CustomerID <> B.CustomerID
AND A.City = B.City 
ORDER BY A.City;
Mazhar MIK
źródło
3
+1 Ta odpowiedź jest bardzo ważna, ponieważ w SO jest tak wiele pytań SQL, na które odpowiedzią jest „użyj samosprzężenia”, których ludzie zwykle nie widzą, gdy nie mają wyraźnego (hierarchicznego) odniesienia do siebie.
JimmyB
1
Mimo że jest to kopiowanie makaronu z w3schools, myślę, że powyższa odpowiedź nie wyjaśnia samozłączenia, ale łączenia wewnętrznego, które jest inne.
George K
3

Jest tu wiele poprawnych odpowiedzi, ale jest też odmiana, która jest równie poprawna. Możesz umieścić warunki złączenia w instrukcji złączenia zamiast w klauzuli WHERE.

SELECT e1.emp_id AS 'Emp_ID'
  , e1.emp_name AS 'Emp_Name'
  , e2.emp_id AS 'Manager_ID'
  , e2.emp_name AS 'Manager_Name'
FROM Employee e1 RIGHT JOIN Employee e2 ON e1.emp_id = e2.emp_id

Pamiętaj, że czasami chcesz e1.manager_id> e2.id

Zaletą znajomości obu scenariuszy jest to, że czasami masz mnóstwo warunków WHERE lub JOIN i chcesz umieścić warunki auto-złączenia w drugiej klauzuli, aby kod był czytelny.

Nikt nie odniósł się do tego, co się dzieje, gdy pracownik nie ma menedżera. Co? Nie są one zawarte w zestawie wyników. Co jeśli chcesz uwzględnić pracowników, którzy nie mają menedżerów, ale nie chcesz, aby zwracane były nieprawidłowe kombinacje?

Spróbuj tego szczeniaka;

SELECT e1.emp_id AS 'Emp_ID'
   , e1.emp_name AS 'Emp_Name'
   , e2.emp_id AS 'Manager_ID'
   , e2.emp_name AS 'Manager_Name'
FROM Employee e1 LEFT JOIN Employee e2 
   ON e1.emp_id = e2.emp_id
   AND e1.emp_name = e2.emp_name
   AND e1.every_other_matching_column = e2.every_other_matching_column
BClaydon
źródło
1
Hm, w szczeniaku, dlaczego łączysz się z „większym niż” zamiast „równy”?
Marcel,
1
Cześć. Widziałem, że niektóre przykłady używają „OD xxx, yyy GDZIE”, a inne „OD xxx JOIN yyy GDZIE”. Czy mógłbyś wyjaśnić różnicę, proszę?
skan
@Skan To naprawdę dobre pytanie. Krótka odpowiedź jest taka, że ​​jest to stara skrócona metoda i zostanie wycofana. Używałem go w szkole 10 + lat temu i rzadko widzę go w praktyce. Oto najbardziej zwięzły opis, jaki udało mi się znaleźć: bidn.com/blogs/KathiKellenberger/sql-server/2875/…
BClaydon,
1

Jednym z przypadków użycia jest sprawdzanie zduplikowanych rekordów w bazie danych.

SELECT A.Id FROM My_Bookings A, My_Bookings B
WHERE A.Name = B.Name
AND A.Date = B.Date
AND A.Id != B.Id
Molossus Spondee
źródło
O wiele szybciej można znaleźć duplikaty za pomocą klauzuli GROUP BY i a HAVING. WYBIERZ imię i nazwisko, adres e-mail, COUNT ( ) FROM My_Bookings GROUP BY name, date HAVING COUNT ( )> 1
George K
@GeorgeK True. Przypuszczam, że jest to konieczne tylko w przypadku dopasowania rozmytego (poza grupowaniem według TRIM (LOWER (nazwa))), a nie w przypadku ścisłej równości.
Molossus Spondee
1

Łączenie samoczynne jest przydatne, gdy musisz ocenić dane tabeli na sobie. Co oznacza, że ​​skoreluje wiersze z tej samej tabeli.

Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName

Na przykład chcemy znaleźć nazwiska pracowników, których początkowe oznaczenie jest równe obecnemu oznaczeniu. Możemy rozwiązać ten problem za pomocą funkcji łączenia automatycznego w następujący sposób.

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId
Sumanth Varada
źródło
0

Jest to odpowiednik bazy danych połączonej listy / drzewa, gdzie wiersz zawiera w pewnym zakresie odniesienie do innego wiersza.

Niepodcięte
źródło
W rzeczywistości, biorąc pod uwagę, że więcej niż jeden wiersz może odnosić się do „rodzica”, może to być również drzewo, jak w często cytowanym przykładzie pracownik-> kierownik.
NVRAM
Po prostu szukałem prostej analogii, ale tak, drzewo też może działać.
Unsliced
-4

Oto wyjaśnienie samołączenia w kategoriach laika. Łączenie własne nie jest innym typem łączenia. Jeśli rozumiesz inne typy złączeń (połączenia wewnętrzne, zewnętrzne i krzyżowe), złączenie samoczynne powinno być proste. W POŁĄCZENIACH WEWNĘTRZNYCH, ZEWNĘTRZNYCH i KRZYŻOWYCH dołączasz 2 lub więcej różnych stołów. Jednak w przypadku samodzielnego dołączania dołączasz do tego samego stołu. Tutaj nie mamy 2 różnych tabel, ale traktujemy tę samą tabelę jako inną tabelę przy użyciu aliasów tabel. Jeśli nadal nie jest to jasne, polecam obejrzenie następujących filmów z YouTube.

Dołącz do siebie na przykładzie

user1472512
źródło