Database
 sql >> база данни >  >> RDS >> Database

Урок за SQL присъединяване

SQL присъединяването е мястото, където изпълнявате заявка, която обединява множество таблици.

Този урок за SQL присъединяване представя основни примери за SQL присъединявания, както и въведение в различните типове присъединяване.

Типове на присъединяване към SQL

Стандартът ANSI SQL определя пет типа обединения, както е изброено в следващата таблица.

Тип на присъединяване Описание

INNER JOIN
Връща редове, когато има поне един ред и в двете таблици, който отговаря на условието за присъединяване.

LEFT OUTER JOIN
или
LEFT JOIN
Връща редове, които имат данни в лявата таблица (вляво от JOIN ключова дума), дори ако няма съвпадащи редове в дясната таблица.

RIGHT OUTER JOIN
или
RIGHT JOIN
Връща редове, които имат данни в дясната таблица (вдясно от JOIN ключова дума), дори ако в лявата таблица няма съвпадащи редове.

FULL OUTER JOIN
или
FULL JOIN
Връща всички редове, стига да има съвпадащи данни в една от таблиците.
CROSS JOIN Връща редове, които комбинират всеки ред от първата таблица с всеки ред от втората таблица.

Съществуват и други термини за различни операции за присъединяване, като например следните:

Присъединете се Описание
Самоприсъединяване Когато таблица се присъедини към себе си.
Естествено присъединяване Неявно присъединяване, базирано на общите колони в двете таблици, които се свързват.
Екви-съединяване Обединение, съдържащо само сравнения на равенство в предиката на присъединяване.

Синтаксис за присъединяване към SQL

Вътрешните съединения могат да бъдат посочени или в FROM или WHERE клаузи. Външните и кръстосаните съединения могат да бъдат посочени в FROM само клауза.

За да създадете SQL присъединяване в FROM клауза, направете нещо подобно:

SELECT *
FROM Table1 < JoinType > Table2 [ ON ( JoinCondition ) ] 

Където JoinType указва какъв вид присъединяване се извършва и JoinCondition дефинира предиката, който да бъде оценен за всяка двойка съединени редове.

За да посочите присъединяване в WHERE клауза, направете нещо подобно:

SELECT *
FROM Table1, Table2 [ WHERE ( JoinCondition ) ] 

Отново JoinCondition дефинира предиката, който да бъде оценен за всяка двойка съединени редове.

Също така всичко, оградено в квадратни скоби ([] ) е по избор.

Примерни таблици за примерите в този урок

Повечето от примерите в този урок изпълняват обединявания срещу следните две таблици.

PetTypes таблица:

+------------+-----------+| PetTypeId | PetType ||-------------+-----------|| 1 | Птица || 2 | Котка || 3 | Куче || 4 | Заек |+------------+-----------+(4 реда засегнати)

Pets таблица:

+--------+------------+-----------+---------- -+-----------+| PetId | PetTypeId | Id на собственик | Име на домашни любимци | DOB ||---------+------------+-----------+----------- +-----------|| 1 | 2 | 3 | Пухкави | 20.11.2020 || 2 | 3 | 3 | Вземи | 2019-08-16 || 3 | 2 | 2 | Надраскване | 01.10.2018 || 4 | 3 | 3 | Размахване | 2020-03-15 || 5 | 1 | 1 | Tweet | 28.11.2020 || 6 | 3 | 4 | Пухкави | 17.09.2020 || 7 | 3 | 2 | Кора | NULL || 8 | 2 | 4 | Мяу | NULL |+--------+------------+-----------+----------- +-----------+(8 засегнати реда)

Вътрешното съединение

SQL INNER JOIN връща редове, когато има поне един ред и в двете таблици, който отговаря на условието за присъединяване.

SELECT
    Pets.PetName,
    PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId; 

Резултат:

-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Котка || Вземи | Куче || Надраскване | Котка || Размахване | Куче || Tweet | Птица || Пухкави | Куче || Кора | Куче || Мяу | Котка |+-----------+-----------+(8 реда засегнати)

За да посочите вътрешно присъединяване в FROM клауза, ние използваме INNER JOIN . Ние също така използваме ON ключова дума за дефиниране на предиката, който да бъде оценен за всяка двойка съединени редове.

Независимо от типа на присъединяването, ние квалифицираме имената на колоните си с имената на таблиците. Причината да правим това е, за да избегнем неясноти по отношение на имената на колоните между таблиците. И двете таблици могат да имат колони с едно и също име (както в нашия пример) и в такива случаи СУБД няма да знае коя колона имате предвид. Поставянето на префикс на имената на колоните с имената на техните таблици гарантира, че препращате към дясната колона и предотвратява всякакви грешки, които биха могли да възникнат от неяснота относно това коя колона имате предвид.

В този пример и двете таблици имат PetTypeId колона. Pets.PetTypeId колоната е външен ключ към PetTypes.PetTypeId колона, която е първичният ключ за тази таблица.

В този пример можем да видим, че всички домашни любимци са върнати, но не всички видове домашни любимци са върнати. В Pets няма зайци таблицата и така Rabbits тип домашни любимци не се връща.

Причината Rabbits типът не се връща, защото INNER JOIN връща редове само когато има поне един ред и в двете таблици, който отговаря на условието за присъединяване. В този случай Rabbits е само в една таблица (PetTypes таблица).

Имайте предвид, че типът на присъединяване не е задължителен. Следователно повечето (ако не всички) СУБД ви позволяват да пропуснете INNER ключова дума. Когато пропуснете това (т.е. посочете само JOIN ), се приема, че е вътрешно съединение.

Следователно бихме могли да пренапишем горния пример на това:

SELECT
    Pets.PetName,
    PetTypes.PetType
FROM Pets
JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId; 

Също така, както при всеки SQL израз, FROM клаузата може да бъде на един цял ред, ако предпочитате:

SELECT
    Pets.PetName,
    PetTypes.PetType
FROM Pets JOIN PetTypes ON Pets.PetTypeId = PetTypes.PetTypeId; 

Псевдоними

Обичайна практика е да се използват псевдоними на таблици, когато се извършват SQL присъединявания. Псевдонимите помагат да направите кода по-сбит и по-лесен за четене.

Следователно бихме могли да променим предишния пример на този:

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId; 

Резултат:

-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Котка || Вземи | Куче || Надраскване | Котка || Размахване | Куче || Tweet | Птица || Пухкави | Куче || Кора | Куче || Мяу | Котка |+-----------+-----------+(8 реда засегнати)

The Equi-Join

Горното присъединяване може също да се нарича equi-join . Equi-join е съединение, съдържащо само сравнения на равенство в предиката на присъединяване.

Друг начин за писане на горното присъединяване е така:

SELECT
    p.PetName,
    pt.PetType
FROM 
    Pets p, 
    PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Котка || Вземи | Куче || Надраскване | Котка || Размахване | Куче || Tweet | Птица || Пухкави | Куче || Кора | Куче || Мяу | Котка |+-----------+-----------+

Това е пример за определяне на вътрешно присъединяване в WHERE клауза. Просто предоставихме разделен със запетая списък на таблиците и след това WHERE състояние. Ако сме пропуснали WHERE условие, щяхме да завършим с CROSS JOIN .

Много начинаещи намират горния синтаксис за много по-лесен за разбиране от INNER JOIN синтаксис. Чувствайте се свободни да използвате този синтаксис, ако предпочитате, но имайте предвид, че повечето специалисти по SQL предпочитат да използват INNER JOIN синтаксис от предишния пример.

Вижте SQL Inner Join за повече примери, включително вътрешно свързване, което свързва 3 таблици.

Правилното присъединяване

Известен също като RIGHT OUTER JOIN , RIGHT JOIN връща редове, които имат данни в дясната таблица (вдясно от JOIN ключова дума), дори ако в лявата таблица няма съвпадащи редове.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
RIGHT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Tweet | Птица || Пухкави | Котка || Надраскване | Котка || Мяу | Котка || Вземи | Куче || Размахване | Куче || Пухкави | Куче || Кора | Куче || NULL | Заек |+-----------+-----------+(9 реда засегнати)

В този случай имаме допълнителен PetType стойност – Rabbit – въпреки че в Pets няма домашен любимец таблица от този тип. Това води до NULL стойност в PetName колона срещу Rabbit .

Вижте SQL Right Join за повече примери, включително дясно присъединяване, което свързва 3 таблици.

Лявото присъединяване

Известен също като LEFT OUTER JOIN , SQL LEFT JOIN връща редове, които имат данни в лявата таблица (вляво от JOIN ключова дума), дори ако в дясната таблица няма съвпадащи редове.

Това е обратното на RIGHT JOIN .

Ако променим предишния пример, за да използваме ляво присъединяване, получаваме следния резултат.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Котка || Вземи | Куче || Надраскване | Котка || Размахване | Куче || Tweet | Птица || Пухкави | Куче || Кора | Куче || Мяу | Котка |+-----------+-----------+(8 реда засегнати)

В този конкретен случай нашите резултати са същите като при вътрешното съединение.

Ако обаче сменим реда на таблицата в нашия FROM клауза, ще получим подобен резултат за дясното присъединяване в предишния пример.

SELECT 
    p.PetName,
    pt.PetType
FROM PetTypes pt
LEFT JOIN Pets p
ON p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Tweet | Птица || Пухкави | Котка || Надраскване | Котка || Мяу | Котка || Вземи | Куче || Размахване | Куче || Пухкави | Куче || Кора | Куче || NULL | Заек |+-----------+-----------+(9 реда засегнати)

Така че можете да видите, че всяка получена разлика между лявото и дясното свързване зависи единствено от това как подреждате колоните в FROM клауза.

Вижте SQL Left Join за повече примери, включително ляво присъединяване, което свързва 3 таблици.

Пълното присъединяване

SQL FULL JOIN (или FULL OUTER JOIN ) връща всички редове, стига да има съвпадащи данни в една от таблиците.

С други думи, това е като да имате и ляво, и дясно присъединяване в едно присъединяване.

Ето пример за пълно присъединяване.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Котка || Вземи | Куче || Надраскване | Котка || Размахване | Куче || Tweet | Птица || Пухкави | Куче || Кора | Куче || Мяу | Котка || NULL | Заек |+-----------+-----------+(9 реда засегнати)

Това връща същия резултат, който получихме с дясното присъединяване, но би върнал различен резултат, ако имаше ред в лявата таблица, който нямаше съответната стойност в дясната таблица.

Нека разменим имената на таблиците и да я стартираме отново.

SELECT 
    p.PetName,
    pt.PetType
FROM PetTypes pt
FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Tweet | Птица || Пухкави | Котка || Надраскване | Котка || Мяу | Котка || Вземи | Куче || Размахване | Куче || Пухкави | Куче || Кора | Куче || NULL | Заек |+-----------+-----------+(9 реда засегнати)

Същият резултат.

Вижте Пълно присъединяване на SQL за повече примери, включително пълно присъединяване, което свързва 3 таблици.

Кръстосаното присъединяване

SQL CROSS JOIN връща редове, които комбинират всеки ред от първата таблица с всеки ред от втората таблица.

С други думи, той връща декартовото произведение на редовете от таблици в обединението.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Птица || Вземи | Птица || Надраскване | Птица || Размахване | Птица || Tweet | Птица || Пухкави | Птица || Кора | Птица || Мяу | Птица || Пухкави | Котка || Вземи | Котка || Надраскване | Котка || Размахване | Котка || Tweet | Котка || Пухкави | Котка || Кора | Котка || Мяу | Котка || Пухкави | Куче || Вземи | Куче || Надраскване | Куче || Размахване | Куче || Tweet | Куче || Пухкави | Куче || Кора | Куче || Мяу | Куче || Пухкави | Заек || Вземи | Заек || Надраскване | Заек || Размахване | Заек || Tweet | Заек || Пухкави | Заек || Кора | Заек || Мяу | Заек |+-----------+-----------+(32 реда засегнати)

Както вероятно можете да си представите, това може да бъде много опасно, ако го стартирате срещу грешни таблици.

Това е същото като да направите това:

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p, PetTypes pt; 

Можете да добавите WHERE клауза към кръстосано съединение, което ще го превърне във вътрешно съединение.

Като това:

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId; 

Резултат:

+-----------+-----------+| Име на домашни любимци | PetType ||-----------+-----------|| Пухкави | Котка || Вземи | Куче || Надраскване | Котка || Размахване | Куче || Tweet | Птица || Пухкави | Куче || Кора | Куче || Мяу | Котка |+-----------+-----------+(8 реда засегнати)

Вижте SQL Cross Join за повече примери.

Естественото присъединяване

SQL NATURAL JOIN е тип equi-join, при който предикатът за присъединяване възниква имплицитно чрез сравняване на всички колони в двете таблици, които имат еднакви имена на колони в обединените таблици.

Резултатът съдържа само една колона за всяка двойка колони с еднакво име. Ако не бъдат намерени колони със същите имена, резултатът ще бъде кръстосано свързване.

SELECT 
    Pets.PetName,
    PetTypes.PetType
FROM Pets NATURAL JOIN PetTypes; 

Резултат:

<предварително име на домашен любимец | домашни любимци ---------+-------- Пухкави | Извличане на котка | Кучешка драскотина | Котешко размахване | Куче Туит | Bird Fluffy | Кучешки лай | Куче Мяу | Котка (8 реда)

Всъщност естественото присъединяване всъщност не е тип присъединяване, както се счита от стандарта ANSI. Това е ключова дума, която можете да вмъкнете по избор, за да направите присъединяването естествено.

Следователно бихме могли да променим горния пример на NATURAL INNER JOIN ако искаме:

SELECT 
    Pets.PetName,
    PetTypes.PetType
FROM Pets NATURAL INNER JOIN PetTypes; 

Както споменахме по-рано, вътрешните съединения са типът на присъединяване по подразбиране, така че ако пропуснете типа на присъединяване (напр. INNER , LEFT , RIGHT и т.н.), след което се третира като вътрешно съединение.

Ако форматирането на тези резултати изглежда различно от предишните резултати, това е защото трябваше да прескоча към PostgreSQL, за да изпълня тази заявка. Пуснах предишните примери в SQL Server, но SQL Server не поддържа естественото присъединяване.

Вижте SQL Natural Join за повече примери, включително естествено присъединяване, което свързва 3 таблици.

Самоприсъединяването

SQL SELF JOIN присъединява маса към себе си.

Класически пример за самостоятелно присъединяване е в таблица на служителите. В такава таблица един служител може да докладва на друг служител. Следователно, можете да използвате самостоятелно присъединяване, за да се присъедините към таблицата в колоната за идентификационен номер на служител и колоната с идентификационен номер на мениджър.

Да предположим, че имаме следната таблица:

+--------------+------------+------------+---- ---------+| EmployeeId | Име | Фамилия | Доклади до ||--------------+------------+------------+----- --------|| 1 | Омир | Конъри | NULL || 2 | Барт | Пит | 1 || 3 | Маги | Грифин | 1 || 4 | Петър | Фарнсуърт | 2 || 5 | Мардж | Морисън | NULL || 6 | Лиза | Партида | 5 || 7 | Дейв | Зукърбърг | 6 || 8 | Влад | Готви | 7 |+--------------+------------+------------+----- --------+

Можем да направим самостоятелно присъединяване към тази маса, за да върнем всички служители и техните мениджъри.

SELECT
    CONCAT(e1.FirstName, ' ', e1.LastName) AS Employee,
    CONCAT(e2.FirstName, ' ', e2.LastName) AS Manager
FROM Employees e1
LEFT JOIN Employees e2 
ON e1.ReportsTo = e2.EmployeeId; 

Резултат:

+-----------------+----------------+| Служител | Мениджър ||-----------------+----------------|| Хоумър Конъри | || Барт Пит | Хоумър Конъри || Маги Грифин | Хоумър Конъри || Питър Фарнсуърт | Барт Пит || Мардж Морисън | || Лиза Бач | Мардж Морисън || Дейв Зукърбърг | Лиза Бач || Влад Кук | Дейв Зукърбърг |+-----------------+----------------+

Вижте SQL Self Join за повече примери.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на Jenkins с Kubernetes AWS, част 1

  2. Грешка в индексиран изглед със скаларни агрегати

  3. Модел на данни за сватбена организация

  4. SCD тип 3

  5. NULL сложности – част 2