Wyjaśnienie samoistnego łączenia się

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

Prosty przykład byłby bardzo pomocny.

Author: Mat, 2010-03-17

12 answers

SELF-join można wyświetlić jako dwie identyczne tabele. Ale w normalizacji nie można utworzyć dwóch kopii tabeli, więc po prostu symulować posiadanie dwóch tabel z samoczynnym połączeniem.

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

Tabela emp1

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

Tabela emp2

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   
Teraz, jeśli chcesz uzyskać nazwisko każdego pracownika z nazwiskami jego lub jej szefa:]}
select c1.Name , c2.Name As Boss
from emp1 c1
    inner join emp2 c2 on c1.Boss_id = c2.Id

, która wyświetli następującą tabelę:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF
 72
Author: pointlesspolitics,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-11 20:52:49

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 Ty chcesz wymienić wszystkich pracowników i nazwisko ich Menedżera.

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id
 19
Author: windyjonas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-16 22:15:52

Self join jest połączeniem tabeli z samym sobą.

Powszechnym przypadkiem użycia jest to, że tabela przechowuje encje (rekordy), które mają hierarchiczną relację między nimi. Na przykład tabela zawierająca informacje o osobie (imię i nazwisko, data urodzenia, adres...) wraz z kolumną, w której znajduje się identyfikator Ojca (i / lub matki). Następnie z małym zapytaniem 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

Możemy uzyskać informacje zarówno o dziecku, jak i ojcu (i matce, z drugim dołączeniem siebie itp. i nawet dziadkowie itp...) w tym samym zapytaniu.

 16
Author: mjv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-10 21:31:06

Powiedzmy, że masz tabelę users, ustawioną TAK:

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

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

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
 5
Author: ceejayoz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-16 22:15:19

Są przydatne, jeśli twoja tabela jest samo-referencjalna. Na przykład dla tabeli stron każda strona może mieć łącze next i previous. Będą to identyfikatory innych stron w tej samej tabeli. Jeśli w pewnym momencie chcesz uzyskać potrójne kolejne strony, wykonaj dwa samouzłącza na kolumnach next i previous z kolumną id tej samej tabeli.

 4
Author: Max Shawabkeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-16 22:16:03

Bez możliwości odwoływania się do samej tabeli, musielibyśmy utworzyć tyle tabel dla poziomów hierarchii, ile liczba warstw w hierarchii. Ale ponieważ ta funkcjonalność jest dostępna, łączysz tabelę z samą sobą, a sql traktuje ją jako dwie oddzielne tabele, więc wszystko jest ładnie przechowywane w jednym miejscu.

 4
Author: Eugene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-16 22:25:05

Wyobraź sobie tabelę o nazwie Employee, jak opisano poniżej. Wszyscy pracownicy mają menedżera, który jest również pracownikiem (może z wyjątkiem dyrektora generalnego, którego manager_id byłby null)

Table (Employee): 

int id,
varchar name,
int manager_id

Możesz użyć następującego wyboru, 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
 3
Author: Klaus Byskov Pedersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-16 22:22:14

Jest tu wiele poprawnych odpowiedzi, ale jest też taka odmiana, która jest równie poprawna. Warunki join możesz umieścić w instrukcji join zamiast 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 czasami, że chcesz e1.manager_id > e2.id

Zaletą znajomości obu scenariuszy jest to, że czasami masz mnóstwo warunków gdzie lub dołącz i chcesz umieścić swoje własne warunki przyłączenia w drugiej klauzuli, aby zachować czytelność kodu.

Nikt nie odniósł się do tego, co się dzieje gdy pracownik nie ma menedżera. Co? Nie są one uwzględniane w zestawie wyników. Co zrobić, jeśli chcesz uwzględnić pracowników, którzy nie mają menedżerów, ale nie chcesz, aby zwracano 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
 3
Author: BClaydon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-02 18:07:55

Oprócz powyższych odpowiedzi (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 klienci, która ma następujące atrybuty: CustomerID, CustomerName, ContactName, City, Country. Teraz chcesz wymienić wszystkich tych, którzy są z "tego samego miasta". Będziesz musiał pomyśleć o replice tej tabeli, abyśmy mogli dołączyć do nich na podstawie miasta. Poniższe zapytanie jasno pokaże, co to oznacza:

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;
 3
Author: Mazhar MIK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-07 06:30:12

Jednym z przypadków użycia jest sprawdzanie duplikatów 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
 1
Author: Steven Stewart-Gallus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-14 21:01:51

Jest bazodanowym odpowiednikiem połączonej listy / drzewa, gdzie wiersz zawiera odniesienie do innego wiersza.

 0
Author: Unsliced,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-17 08:03:32

Oto eksaplanacja jaźni w kategoriach laika. Self join nie jest innym rodzajem join. Jeśli zrozumiałeś inne rodzaje połączeń (Wewnętrzne, Zewnętrzne I krzyżowe połączenia), wtedy SELF join powinno być proste do przodu. W połączeniach wewnętrznych, zewnętrznych i krzyżowych łączysz 2 lub więcej różnych tabel. Jednak w self join dołączasz do tej samej tabeli z itslef. Tutaj nie mamy dwóch różnych tabel, ale traktujemy tę samą tabelę jako inną tabelę za pomocą aliasów tabel. Jeśli nadal nie jest to jasne, chciałbym polecam obejrzeć następujące filmy z youtube.

Self Join with an example

 -4
Author: user1472512,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-31 13:25:03