Я не понимаю необходимости самообъединений. Может кто-нибудь объяснить их мне?
Простой пример был бы очень полезен.
Я не понимаю необходимости самообъединений. Может кто-нибудь объяснить их мне?
Простой пример был бы очень полезен.
Самообъединение можно рассматривать как две идентичные таблицы. Но при нормализации вы не можете создать две копии таблицы, поэтому вы просто имитируете наличие двух таблиц с самообъединением.
Предположим, у вас есть две таблицы:
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
left join
Я думаю, что было бы лучше не оставлять без внимания сотрудника (или начальника), у которого нет начальника; топ собака!
- person Rockin4Life33; 05.09.2018
Это довольно распространено, когда у вас есть таблица, которая ссылается сама на себя. Пример: таблица сотрудников, в которой у каждого сотрудника может быть менеджер, и вы хотите перечислить всех сотрудников и имя их менеджера.
SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id
Самосоединение — это соединение таблицы с самой собой.
Общий вариант использования — когда в таблице хранятся объекты (записи), между которыми существует иерархическая связь. Например, таблица, содержащая информацию о человеке (имя, дата рождения, адрес...) и включающая столбец, в который включен идентификатор отца (и/или матери). Затем с небольшим запросом, например
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
мы можем получить информацию как о ребенке, так и об отце (и матери, со вторым самостоятельным соединением и т. д., и даже о великих родителях и т. д.) в одном запросе.
Допустим, у вас есть таблица 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
Представьте себе таблицу с именем 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
Они полезны, если ваша таблица является самореферентной. Например, для таблицы страниц каждая страница может иметь ссылку next
и previous
. Это будут идентификаторы других страниц в той же таблице. Если в какой-то момент вы захотите получить тройку последовательных страниц, вы должны выполнить два самосоединения в столбцах next
и previous
со столбцом id
той же таблицы.
Без возможности таблицы ссылаться на себя нам пришлось бы создавать столько таблиц для уровней иерархии, сколько слоев в иерархии. Но поскольку эта функциональность доступна, вы соединяете таблицу с самой собой, и sql обрабатывает ее как две отдельные таблицы, поэтому все удобно хранится в одном месте.
Помимо ответов, упомянутых выше (которые очень хорошо объяснены), я хотел бы добавить один пример, чтобы можно было легко показать использование Self Join. Предположим, у вас есть таблица CUSTOMERS со следующими атрибутами: 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;
Здесь много правильных ответов, но есть вариант, не менее правильный. Вы можете поместить условия соединения в оператор соединения вместо предложения 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
Преимущество знания обоих сценариев заключается в том, что иногда у вас есть масса условий WHERE или JOIN, и вы хотите поместить свои условия самостоятельного соединения в другое предложение, чтобы ваш код был читабельным.
Никто не обращался к тому, что происходит, когда у Сотрудника нет менеджера. Хм? Они не включены в набор результатов. Что делать, если вы хотите включить сотрудников, у которых нет менеджеров, но не хотите, чтобы возвращались неправильные комбинации?
Попробуйте этого щенка;
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
Одним из вариантов использования является проверка дубликатов записей в базе данных.
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
Самосоединение полезно, когда вам нужно оценить данные таблицы с самой собой. Это означает, что он будет сопоставлять строки из одной и той же таблицы.
Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName
Например, мы хотим найти имена сотрудников, чье первоначальное назначение совпадает с текущим назначением. Мы можем решить это, используя самосоединение следующим образом.
SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId
Это эквивалент базы данных связанного списка/дерева, где строка содержит ссылку в той или иной степени на другую строку.
Вот объяснение самостоятельного соединения с точки зрения непрофессионала. Самосоединение не является другим типом соединения. Если вы знакомы с другими типами соединений (внутренними, внешними и перекрестными соединениями), то самостоятельное соединение должно быть простым. В INNER, OUTER и CROSS JOINS вы объединяете 2 или более разных таблиц. Однако при самосоединении вы присоединяетесь к одной и той же таблице с ее левым звеном. Здесь у нас нет двух разных таблиц, но мы рассматриваем одну и ту же таблицу как другую таблицу, используя псевдонимы таблиц. Если это все еще не ясно, я бы рекомендовал посмотреть следующие видео на YouTube.
Самостоятельное присоединение с примером