Część 1 - Połączenia i związki
Ta odpowiedź obejmuje:
- Część 1
- Łączenie dwóch lub więcej tabel za pomocą łączenia wewnętrznego ( dodatkowe informacje można znaleźć we wpisie na Wikipedii )
- Jak korzystać z kwerendy związkowej
- Lewe i prawe połączenia zewnętrzne (ta odpowiedź StackOverflow doskonale nadaje się do opisywania rodzajów połączeń)
- Przecinaj zapytania (i jak je reprodukować, jeśli twoja baza danych ich nie obsługuje) - jest to funkcja SQL-Server ( patrz informacje ) i po części dlatego napisałem to wszystko .
- Część 2
- Podkwerendy - czym są, gdzie można ich używać i na co uważać
- Kartezjan dołącza do AKA - Och, nędza!
Istnieje wiele sposobów wyszukiwania danych z wielu tabel w bazie danych. W tej odpowiedzi użyję składni złączenia ANSI-92. Może się to różnić od wielu innych samouczków, które używają starszej składni ANSI-89 (a jeśli jesteś przyzwyczajony do 89, może wydawać się znacznie mniej intuicyjny - ale wszystko, co mogę powiedzieć, to wypróbować), ponieważ jest to o wiele łatwiejsze aby zrozumieć, kiedy zapytania stają się bardziej złożone. Po co z tego korzystać? Czy jest wzrost wydajności? Krótka odpowiedź nie jest, ale jest łatwiejsze do odczytania po przyzwyczaić się do niego. Łatwiej jest czytać zapytania napisane przez innych ludzi za pomocą tej składni.
Zamierzam również wykorzystać koncepcję małego caryarda, który ma bazę danych do śledzenia dostępnych samochodów. Właściciel wynajął cię jako swojego informatyka i oczekuje, że będziesz w stanie upuścić mu dane, o które prosi po kropli kapelusza.
Zrobiłem wiele tabel odnośników, które będą używane przy stole finałowym. To da nam rozsądny model do pracy. Na początek będę uruchamiać moje zapytania na przykładowej bazie danych o następującej strukturze. Spróbuję wymyślić typowe błędy popełniane na początku i wyjaśnić, co się z nimi dzieje - a także oczywiście pokażę, jak je naprawić.
Pierwszy stół to po prostu lista kolorów, dzięki czemu wiemy, jakie kolory mamy na podwórzu samochodowym.
mysql> create table colors(id int(3) not null auto_increment primary key,
-> color varchar(15), paint varchar(10));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | varchar(15) | YES | | NULL | |
| paint | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> insert into colors (color, paint) values ('Red', 'Metallic'),
-> ('Green', 'Gloss'), ('Blue', 'Metallic'),
-> ('White' 'Gloss'), ('Black' 'Gloss');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from colors;
+----+-------+----------+
| id | color | paint |
+----+-------+----------+
| 1 | Red | Metallic |
| 2 | Green | Gloss |
| 3 | Blue | Metallic |
| 4 | White | Gloss |
| 5 | Black | Gloss |
+----+-------+----------+
5 rows in set (0.00 sec)
Tabela marek identyfikuje różne marki samochodów, które caryard mógłby sprzedać.
mysql> create table brands (id int(3) not null auto_increment primary key,
-> brand varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from brands;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| brand | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> insert into brands (brand) values ('Ford'), ('Toyota'),
-> ('Nissan'), ('Smart'), ('BMW');
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from brands;
+----+--------+
| id | brand |
+----+--------+
| 1 | Ford |
| 2 | Toyota |
| 3 | Nissan |
| 4 | Smart |
| 5 | BMW |
+----+--------+
5 rows in set (0.00 sec)
Tabela modeli obejmie różne typy samochodów, łatwiej będzie korzystać z różnych typów samochodów niż z rzeczywistych modeli samochodów.
mysql> create table models (id int(3) not null auto_increment primary key,
-> model varchar(15));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from models;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| model | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> insert into models (model) values ('Sports'), ('Sedan'), ('4WD'), ('Luxury');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from models;
+----+--------+
| id | model |
+----+--------+
| 1 | Sports |
| 2 | Sedan |
| 3 | 4WD |
| 4 | Luxury |
+----+--------+
4 rows in set (0.00 sec)
I wreszcie, aby związać wszystkie te inne stoły, stół, który łączy wszystko razem. Pole ID jest w rzeczywistości unikalnym numerem partii używanym do identyfikacji samochodów.
mysql> create table cars (id int(3) not null auto_increment primary key,
-> color int(3), brand int(3), model int(3));
Query OK, 0 rows affected (0.01 sec)
mysql> show columns from cars;
+-------+--------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+----------------+
| id | int(3) | NO | PRI | NULL | auto_increment |
| color | int(3) | YES | | NULL | |
| brand | int(3) | YES | | NULL | |
| model | int(3) | YES | | NULL | |
+-------+--------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> insert into cars (color, brand, model) values (1,2,1), (3,1,2), (5,3,1),
-> (4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> select * from cars;
+----+-------+-------+-------+
| id | color | brand | model |
+----+-------+-------+-------+
| 1 | 1 | 2 | 1 |
| 2 | 3 | 1 | 2 |
| 3 | 5 | 3 | 1 |
| 4 | 4 | 4 | 2 |
| 5 | 2 | 2 | 3 |
| 6 | 3 | 5 | 4 |
| 7 | 4 | 1 | 3 |
| 8 | 2 | 2 | 1 |
| 9 | 5 | 2 | 3 |
| 10 | 4 | 5 | 1 |
+----+-------+-------+-------+
10 rows in set (0.00 sec)
To da nam wystarczającą ilość danych (mam nadzieję), aby zilustrować poniższe przykłady różnych rodzajów złączeń, a także dostarczy wystarczającą ilość danych, aby były warte zachodu.
Wchodząc w sedno, szef chce poznać identyfikatory wszystkich samochodów sportowych, które ma .
To proste połączenie dwóch tabel. Mamy tabelę, która identyfikuje model i tabelę z dostępnymi zapasami. Jak widać, dane w model
kolumnie cars
tabeli odnoszą się do models
kolumny cars
tabeli, którą mamy. Teraz wiemy, że tabela modeli ma identyfikator 1
dla, Sports
więc napiszmy złączenie.
select
ID,
model
from
cars
join models
on model=ID
Więc to zapytanie wygląda dobrze, prawda? Zidentyfikowaliśmy dwie tabele i zawierają potrzebne informacje, a następnie używamy złączenia, które poprawnie identyfikuje kolumny, które należy dołączyć.
ERROR 1052 (23000): Column 'ID' in field list is ambiguous
Och nie! Błąd w naszym pierwszym zapytaniu! Tak, i to jest śliwka. Widzisz, zapytanie rzeczywiście ma odpowiednie kolumny, ale niektóre z nich istnieją w obu tabelach, więc baza danych jest zdezorientowana co do tego, którą kolumnę mamy na myśli i gdzie. Istnieją dwa rozwiązania tego problemu. Pierwszy jest ładny i prosty, możemy użyć tableName.columnName
bazy danych, aby dokładnie powiedzieć, co mamy na myśli, w następujący sposób:
select
cars.ID,
models.model
from
cars
join models
on cars.model=models.ID
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
| 2 | Sedan |
| 4 | Sedan |
| 5 | 4WD |
| 7 | 4WD |
| 9 | 4WD |
| 6 | Luxury |
+----+--------+
10 rows in set (0.00 sec)
Drugi jest prawdopodobnie częściej używany i nazywany jest aliasingiem tabel. Tabele w tym przykładzie mają ładne i krótkie proste nazwy, ale wpisanie czegoś takiego KPI_DAILY_SALES_BY_DEPARTMENT
prawdopodobnie szybko się zestarzeje, więc prostym sposobem jest pseudonimowanie tabeli w ten sposób:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
Wróćmy do żądania. Jak widać, mamy informacje, których potrzebujemy, ale mamy również informacje, o które nie poprosiliśmy, dlatego w oświadczeniu musimy zawrzeć klauzulę „where”, aby uzyskać tylko samochody sportowe, o które poproszono. Ponieważ wolę metodę aliasu tabeli niż używanie nazw tabel w kółko, odtąd będę się jej trzymał.
Oczywiście musimy dodać klauzulę where do naszego zapytania. Możemy zidentyfikować samochody sportowe za pomocą ID=1
lub model='Sports'
. Ponieważ identyfikator jest indeksowany, a klucz podstawowy (i zdarza się, że mniej się pisze), użyjmy go w naszym zapytaniu.
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
Bingo! Szef jest szczęśliwy. Oczywiście, będąc szefem i nigdy nie będąc zadowolonym z tego, o co prosił, patrzy na informacje, a następnie mówi, że chcę też kolorów .
Okej, więc duża część naszego zapytania jest już napisana, ale musimy użyć trzeciej tabeli, która jest kolorami. Teraz nasza główna tabela informacyjna cars
przechowuje identyfikator koloru samochodu, który prowadzi do kolumny identyfikatora kolorów. Tak więc, podobnie jak oryginał, możemy dołączyć do trzeciego stołu:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 3 | Sports |
| 8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)
Cholera, chociaż tabela została poprawnie połączona i powiązane kolumny zostały połączone, zapomnieliśmy pobrać rzeczywiste informacje z nowej tabeli, którą właśnie połączyliśmy.
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
where
b.ID=1
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
+----+--------+-------+
4 rows in set (0.00 sec)
Racja, to na chwilę szef od naszych pleców. Teraz wyjaśnię to trochę bardziej szczegółowo. Jak widać, from
klauzula w naszym zestawieniu łączy naszą główną tabelę (często używam tabeli zawierającej informacje zamiast tabeli odnośników lub wymiarów. Zapytanie działałoby równie dobrze z przełączonymi tabelami, ale mniej sensowne, gdy wrócimy do tego zapytania, aby je przeczytać za kilka miesięcy, więc często najlepiej jest napisać zapytanie, które będzie miłe i łatwe do zrozumienia - ułóż je intuicyjnie, użyj ładnego wcięcia, aby wszystko było tak jasne, jak może być. Jeśli będziesz uczyć innych, spróbuj zaszczepić te cechy w ich zapytaniach - szczególnie jeśli będziesz je rozwiązywał.
W ten sposób można nadal łączyć coraz więcej tabel.
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
Chociaż zapomniałem dołączyć tabelę, w której moglibyśmy chcieć dołączyć więcej niż jedną kolumnę do join
instrukcji, oto przykład. Jeśli models
tabela zawiera modele specyficzne dla marki, a zatem ma również kolumnę o nazwie, brand
która łączy się z brands
tabelą w ID
polu, można to zrobić w następujący sposób:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
and b.brand=d.ID
where
b.ID=1
Widzisz, powyższe zapytanie nie tylko łączy połączone tabele z cars
tabelą główną , ale także określa połączenia między już połączonymi tabelami. Jeśli tego nie zrobiono, wynik nazywany jest łączeniem kartezjańskim - co oznacza, że dba mówi źle. Sprzężenie kartezjańskie to takie, w którym zwracane są wiersze, ponieważ informacje nie informują bazy danych, jak ograniczyć wyniki, więc zapytanie zwraca wszystkie wiersze spełniające kryteria.
Aby podać przykład sprzężenia kartezjańskiego, uruchommy następujące zapytanie:
select
a.ID,
b.model
from
cars a
join models b
+----+--------+
| ID | model |
+----+--------+
| 1 | Sports |
| 1 | Sedan |
| 1 | 4WD |
| 1 | Luxury |
| 2 | Sports |
| 2 | Sedan |
| 2 | 4WD |
| 2 | Luxury |
| 3 | Sports |
| 3 | Sedan |
| 3 | 4WD |
| 3 | Luxury |
| 4 | Sports |
| 4 | Sedan |
| 4 | 4WD |
| 4 | Luxury |
| 5 | Sports |
| 5 | Sedan |
| 5 | 4WD |
| 5 | Luxury |
| 6 | Sports |
| 6 | Sedan |
| 6 | 4WD |
| 6 | Luxury |
| 7 | Sports |
| 7 | Sedan |
| 7 | 4WD |
| 7 | Luxury |
| 8 | Sports |
| 8 | Sedan |
| 8 | 4WD |
| 8 | Luxury |
| 9 | Sports |
| 9 | Sedan |
| 9 | 4WD |
| 9 | Luxury |
| 10 | Sports |
| 10 | Sedan |
| 10 | 4WD |
| 10 | Luxury |
+----+--------+
40 rows in set (0.00 sec)
Dobry Boże, to brzydkie. Jednak jeśli chodzi o bazę danych, to dokładnie o to poproszono. W zapytaniu poprosiliśmy o podanie ID
od cars
i model
od models
. Ponieważ jednak nie określiliśmy sposobu łączenia tabel, baza danych dopasowała każdy wiersz z pierwszej tabeli do każdego wiersza z drugiej tabeli.
Okej, więc szef wrócił i znowu chce więcej informacji. Chcę tę samą listę, ale także zawierać w niej 4WD .
To jednak daje nam doskonałą wymówkę, aby spojrzeć na dwa różne sposoby osiągnięcia tego celu. Możemy dodać kolejny warunek do klauzuli where:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
or b.ID=3
Chociaż powyższe będzie działać doskonale, spójrzmy na to inaczej, jest to świetna wymówka, aby pokazać, jak działa union
zapytanie.
Wiemy, że następujące produkty zwrócą wszystkie samochody sportowe:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
A poniższe zwróci wszystkie 4WD:
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
Dodając union all
między nimi klauzulę, wyniki drugiego zapytania zostaną dołączone do wyników pierwszego zapytania.
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=1
union all
select
a.ID,
b.model,
c.color
from
cars a
join models b
on a.model=b.ID
join colors c
on a.color=c.ID
join brands d
on a.brand=d.ID
where
b.ID=3
+----+--------+-------+
| ID | model | color |
+----+--------+-------+
| 1 | Sports | Red |
| 8 | Sports | Green |
| 10 | Sports | White |
| 3 | Sports | Black |
| 5 | 4WD | Green |
| 7 | 4WD | White |
| 9 | 4WD | Black |
+----+--------+-------+
7 rows in set (0.00 sec)
Jak widać, wyniki pierwszego zapytania są zwracane jako pierwsze, a następnie wyniki drugiego zapytania.
W tym przykładzie byłoby oczywiście o wiele łatwiej po prostu użyć pierwszego zapytania, ale union
zapytania mogą być świetne w określonych przypadkach. Są świetnym sposobem na zwrócenie określonych wyników z tabel z tabel, które nie dają się łatwo połączyć - lub, w tym przypadku, całkowicie niepowiązanych tabel. Należy jednak przestrzegać kilku zasad.
- Typy kolumn z pierwszego zapytania muszą pasować do typów kolumn z każdego innego zapytania poniżej.
- Nazwy kolumn z pierwszego zapytania zostaną wykorzystane do zidentyfikowania całego zestawu wyników.
- Liczba kolumn w każdym zapytaniu musi być taka sama.
Być może zastanawiasz się, jaka jest różnica między używaniem union
a union all
. union
Zapytania usunie duplikaty, póki union all
nie będzie. Oznacza to, że podczas korzystania z union
nadmiernej wydajności występuje niewielki spadek wydajności, union all
ale wyniki mogą być tego warte - nie będę jednak spekulował na ten temat.
W tej notatce warto zwrócić uwagę na kilka dodatkowych uwag.
- Jeśli chcielibyśmy zamówić wyniki, możemy użyć,
order by
ale nie możesz już używać aliasu. W powyższym zapytaniu dodanie an order by a.ID
spowoduje błąd - jeśli chodzi o wyniki, kolumna jest wywoływana ID
zamiast a.ID
- mimo że w obu zapytaniach zastosowano ten sam alias.
- Możemy mieć tylko jedno
order by
oświadczenie, które musi być ostatnim oświadczeniem.
Do kolejnych przykładów dodam kilka dodatkowych wierszy do naszych tabel.
Dodałem Holden
do tabeli marek. Dodałem również wiersz, cars
który ma color
wartość 12
- która nie ma odniesienia w tabeli kolorów.
Okej, szef znowu wrócił, szczekając prośbami - * Chcę liczbę każdej przewożonej marki i liczbę samochodów w niej! ”- Typowo, przechodzimy do interesującej części naszej dyskusji, a szef chce więcej pracy .
Rightyo, więc pierwszą rzeczą, którą musimy zrobić, to uzyskać pełną listę możliwych marek.
select
a.brand
from
brands a
+--------+
| brand |
+--------+
| Ford |
| Toyota |
| Nissan |
| Smart |
| BMW |
| Holden |
+--------+
6 rows in set (0.00 sec)
Teraz, gdy dołączymy to do naszej tabeli samochodów, otrzymamy następujący wynik:
select
a.brand
from
brands a
join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Nissan |
| Smart |
| Toyota |
+--------+
5 rows in set (0.00 sec)
Co oczywiście stanowi problem - nie widzimy wzmianki o uroczej Holden
marce, którą dodałem.
Jest tak, ponieważ złączenie szuka pasujących wierszy w obu tabelach. Ponieważ w typach samochodów nie ma danych, Holden
nie są one zwracane. Tutaj możemy użyć outer
złączenia. Spowoduje to zwrócenie wszystkich wyników z jednej tabeli, niezależnie od tego, czy zostaną one dopasowane w drugiej tabeli, czy nie:
select
a.brand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+
| brand |
+--------+
| BMW |
| Ford |
| Holden |
| Nissan |
| Smart |
| Toyota |
+--------+
6 rows in set (0.00 sec)
Teraz, gdy to mamy, możemy dodać uroczą funkcję agregującą, aby policzyć i na chwilę odrzucić bossa.
select
a.brand,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
group by
a.brand
+--------+--------------+
| brand | countOfBrand |
+--------+--------------+
| BMW | 2 |
| Ford | 2 |
| Holden | 0 |
| Nissan | 1 |
| Smart | 1 |
| Toyota | 5 |
+--------+--------------+
6 rows in set (0.00 sec)
A wraz z tym szef odchodzi.
Aby wyjaśnić to bardziej szczegółowo, sprzężenia zewnętrzne mogą być typu left
lub right
. Lewy lub prawy określa, która tabela jest w pełni uwzględniona. A left outer join
obejmie wszystkie wiersze z tabeli po lewej stronie, podczas gdy (zgadłeś) a a right outer join
przenosi wszystkie wyniki z tabeli po prawej stronie do wyników.
Niektóre bazy danych pozwolą na full outer join
przywrócenie wyników (dopasowanych lub nie) z obu tabel, ale nie jest to obsługiwane we wszystkich bazach danych.
Prawdopodobnie w tym momencie myślę, że zastanawiasz się, czy możesz scalić typy złączeń w zapytaniu - a odpowiedź brzmi tak, absolutnie możesz.
select
b.brand,
c.color,
count(a.id) as countOfBrand
from
cars a
right outer join brands b
on b.ID=a.brand
join colors c
on a.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| Ford | Blue | 1 |
| Ford | White | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| BMW | Blue | 1 |
| BMW | White | 1 |
+--------+-------+--------------+
9 rows in set (0.00 sec)
Dlaczego więc nie są to oczekiwane wyniki? Dzieje się tak, ponieważ chociaż wybraliśmy łączenie zewnętrzne od samochodów do marek, nie zostało ono określone w łączeniu z kolorami - więc to konkretne połączenie przyniesie tylko wyniki, które pasują do obu tabel.
Oto zapytanie, które zadziałałoby, aby uzyskać oczekiwane wyniki:
select
a.brand,
c.color,
count(b.id) as countOfBrand
from
brands a
left outer join cars b
on a.ID=b.brand
left outer join colors c
on b.color=c.ID
group by
a.brand,
c.color
+--------+-------+--------------+
| brand | color | countOfBrand |
+--------+-------+--------------+
| BMW | Blue | 1 |
| BMW | White | 1 |
| Ford | Blue | 1 |
| Ford | White | 1 |
| Holden | NULL | 0 |
| Nissan | Black | 1 |
| Smart | White | 1 |
| Toyota | NULL | 1 |
| Toyota | Black | 1 |
| Toyota | Green | 2 |
| Toyota | Red | 1 |
+--------+-------+--------------+
11 rows in set (0.00 sec)
Jak widać, w zapytaniu mamy dwa sprzężenia zewnętrzne, a wyniki są zgodne z oczekiwaniami.
A co powiesz na inne rodzaje złączeń, o które pytasz? Co z skrzyżowaniami?
Cóż, nie wszystkie bazy danych obsługują, intersection
ale prawie wszystkie bazy danych pozwolą ci stworzyć skrzyżowanie poprzez sprzężenie (lub dobrze skonstruowaną instrukcję co najmniej).
Przecięcie jest rodzajem łączenia nieco podobnym do union
opisanego powyżej - ale różnica polega na tym, że zwraca tylko wiersze danych, które są identyczne (i mam na myśli identyczne) między różnymi pojedynczymi zapytaniami połączonymi przez związek. Zwrócone zostaną tylko wiersze identyczne pod każdym względem.
Prostym przykładem byłby taki:
select
*
from
colors
where
ID>2
intersect
select
*
from
colors
where
id<4
Podczas gdy normalne union
zapytanie zwróci wszystkie wiersze tabeli (pierwsze zapytanie zwraca wszystko, ID>2
a drugie ma coś ID<4
), co da pełny zestaw, zapytanie przecinające zwróci tylko dopasowanie wiersza, id=3
ponieważ spełnia oba kryteria.
Teraz, jeśli twoja baza danych nie obsługuje intersect
zapytania, powyższe można łatwo osiągnąć za pomocą następującego zapytania:
select
a.ID,
a.color,
a.paint
from
colors a
join colors b
on a.ID=b.ID
where
a.ID>2
and b.ID<4
+----+-------+----------+
| ID | color | paint |
+----+-------+----------+
| 3 | Blue | Metallic |
+----+-------+----------+
1 row in set (0.00 sec)
Jeśli chcesz wykonać przecięcie między dwoma różnymi tabelami przy użyciu bazy danych, która z natury nie obsługuje zapytania o przecięcie, musisz utworzyć złączenie w każdej kolumnie tabeli.