Пояснення самоприєднання


84

Я не розумію необхідності самостійних приєднань. Хтось може пояснити мені їх?

Простий приклад був би дуже корисним.

Відповіді:


95

Ви можете переглянути самоз’єднання як дві однакові таблиці. Але при нормалізації ви не можете створити дві копії таблиці, тому просто імітуєте наявність двох таблиць із самоз’єднанням.

Припустимо, у вас є дві таблиці:

Таблиця emp1

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

Таблиця emp2

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

Тепер, якщо ви хочете отримати ім’я кожного працівника з іменами його або її начальника:

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

Що виведе наступну таблицю:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF

1
У цьому прикладі я не можу зрозуміти, хто є начальником. Хоча досвід є хорошим і легким для розуміння.
MAC

2
left joinЯ думаю, було б краще, щоб не залишати без уваги працівника (або начальника), який не має начальника; верхня собака!
Rockin4Life33

22

Це досить часто, коли у вас є таблиця, яка посилається на себе. Приклад: таблиця співробітників, де кожен працівник може мати менеджера, і ви хочете перерахувати всіх співробітників та ім’я їх менеджера.

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id

18

Самоз’єднання - це об’єднання таблиці з самим собою.

Поширений випадок, коли таблиця зберігає сутності (записи), які мають ієрархічні відносини між собою . Наприклад, таблиця, що містить інформацію про особу (Ім’я, DOB, Адреса ...), а також стовпець, де міститься ідентифікатор батька (та / або матері). Потім з невеликим запитом типу

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

ми можемо отримати інформацію про дитину та батька (і матір, з другим самостійним приєднанням тощо, і навіть про великих батьків тощо) в тому самому запиті.


5

Скажімо, у вас є таблиця users, налаштована так:

  • ідентифікатор користувача
  • ім'я користувача
  • ідентифікатор менеджера користувача

У цій ситуації, якщо ви хочете , щоб витягти інформацію користувача і інформації менеджера в одному запиті, ви можете зробити це:

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

4

Вони корисні, якщо ваша таблиця є самодовідковою. Наприклад, для таблиці сторінок кожна сторінка може мати посилання nextта previous. Це були б ідентифікатори інших сторінок тієї самої таблиці. Якщо в якийсь момент ви хочете отримати потрійну послідовну сторінку, ви зробите два самостійних приєднання стовпців nextта previousз одним і тим же idстовпцем таблиці .


4

Уявіть собі таблицю, що називається, Employeeяк описано нижче. Усі співробітники мають менеджера, який також є співробітником (можливо, крім генерального директора, ідентифікатор manager_id якого буде нульовим)

Table (Employee): 

int id,
varchar name,
int manager_id

Потім ви можете використовувати наступний вибір, щоб знайти всіх співробітників та їх менеджерів:

select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id

4

Без можливості посилання на таблицю, нам довелося б створити стільки таблиць для рівнів ієрархії, скільки кількість шарів в ієрархії. Але оскільки ця функціональність доступна, ви приєднуєте таблицю до себе і sql розглядає її як дві окремі таблиці, тому все чудово зберігається в одному місці.


але тепер ви (сподіваємось) розумієте, що сталося б, якби самодовідка була недоступна.
Євген

4

Окрім згаданих вище відповідей (які дуже добре пояснені), я хотів би додати один приклад, щоб можна було легко показати використання Self Join. Припустимо, у вас є таблиця з іменем КЛІЄНТИ, яка має такі атрибути: CustomerID, CustomerName, ContactName, City, Country. Тепер ви хочете перерахувати всіх, хто з "того самого міста". Вам доведеться продумати копію цієї таблиці, щоб ми могли приєднатися до них на базі CITY. Запит нижче чітко покаже, що це означає:

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
+1 Ця відповідь дуже важлива, оскільки існує так багато запитань щодо SQL щодо SO, на які відповідає "використати самостійне приєднання", яких люди, як правило, не бачать, коли не мають явного (ієрархічного) посилання на себе.
JimmyB

1
Навіть якщо це копія макаронних виробів від w3schools, я думаю, що наведена вище відповідь не пояснює самостійне приєднання, а внутрішнє приєднання, яке відрізняється.
Джордж К

3

Тут багато правильних відповідей, але є варіація, яка однаково правильно. Ви можете розмістити свої умови приєднання в операторі приєднання замість речення 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

Майте на увазі, іноді ви хочете e1.manager_id> e2.id

Перевага знання обох сценаріїв полягає в тому, що іноді у вас є маса умов ДЕ або ПРИЄДНАЙТЕСЯ, і ви хочете розмістити свої умови самоз’єднання в іншому пункті, щоб ваш код був читабельним.

Ніхто не звертався до того, що відбувається, коли працівник не має менеджера. А? Вони не включені до набору результатів. Що робити, якщо ви хочете включити працівників, які не мають менеджерів, але ви не хочете, щоб поверталися неправильні комбінації?

Спробуйте цього цуценя;

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

1
Хм, у цуценя, чому ви приєднуєтесь до "більше ніж" замість "дорівнює"?
Марсель

1
Привіт. Я бачив, що в деяких прикладах використовується "ВІД xxx, yyy ДЕ" та деякі інші "FROM xxx ПРИЄДНАЙТЕСЬ yyy ДЕ". Не могли б ви пояснити різницю, будь ласка?
skan

@Skan Це справді гарне запитання. Коротка відповідь полягає в тому, що це старий скорочений метод, який буде застарілим. Я використовував його в школі десять років тому і рідко бачу це на практиці. Ось найбільш стислий опис, який я міг знайти: bidn.com/blogs/KathiKellenberger/sql-server/2875/…
BClaydon,

1

Одним із варіантів використання є перевірка на наявність повторюваних записів у базі даних.

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

Набагато швидше використовувати GROUP BY та речення HAVING для пошуку дублікатів. ВИБЕРІТЬ ім'я, електронну адресу, COUNT ( ) З ГРУПИ My_Bookings ЗА ІМ'ЯМ, датою МАТИ COUNT ( )> 1
Джордж К

@GeorgeK Правда. Я вважаю, що це потрібно лише для нечіткого збігу (крім групування за TRIM (LOWER (Name))), а не для суворої рівності.
Steven Stewart-Gallus

1

Самоз’єднання корисно, коли вам потрібно оцінити дані таблиці з собою. Це означає, що він буде співвідносити рядки з однієї таблиці.

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

Наприклад, ми хочемо знайти імена працівників, початкове призначення яких дорівнює поточному. Ми можемо вирішити це, використовуючи самостійне приєднання наступним чином.

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId

0

Це еквівалент бази даних зв’язаного списку / дерева, де рядок містить посилання в якійсь якості на інший рядок.


Насправді, враховуючи те, що більше одного рядка може посилатися на "батька", це може бути також дерево, наприклад, як часто цитований приклад worker-> manager.
NVRAM

Я просто намагався зробити просту аналогію, але так, дерево теж могло працювати.
Незрізаний

-4

Ось пояснення того, як приєднатися до себе, неспеціалістично. Самоз’єднання - це не різний тип об’єднання. Якщо ви зрозуміли інші типи об’єднань (внутрішнє, зовнішнє та перехресне), тоді самостійне об’єднання має бути прямим. У ВНУТРІШНІЙ, ЗОВНІШНІЙ та ХРЕСТОВІЙ СПИСКАХ ви об’єднуєте 2 або більше різних таблиць. Однак, при самостійному приєднанні ви приєднуєтесь до однієї таблиці за допомогою їїліва. Тут у нас немає 2 різних таблиць, але ми обробляємо одну і ту ж таблицю як іншу таблицю, використовуючи псевдоніми таблиць. Якщо це все ще незрозуміло, я рекомендую переглянути наступні відео YouTube.

Self Приєднайтеся з прикладом

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.