Phần 1 - Tham gia và Liên hiệp
Câu trả lời này bao gồm:
- Phần 1
- Tham gia hai hoặc nhiều bảng bằng cách sử dụng kết nối bên trong (Xem mục wikipedia để biết thêm thông tin)
- Cách sử dụng truy vấn công đoàn
- Các liên kết ngoài trái và phải ( câu trả lời stackOverflow này là tuyệt vời để mô tả các loại liên kết)
- Truy vấn xen kẽ (và cách tái tạo chúng nếu cơ sở dữ liệu của bạn không hỗ trợ chúng) - đây là chức năng của SQL-Server ( xem thông tin ) và một phần lý do tôi đã viết toàn bộ điều này ngay từ đầu.
- Phần 2
- Truy vấn con - chúng là gì, chúng có thể được sử dụng ở đâu và những gì cần chú ý
- Cartesian gia nhập AKA - Ôi, khốn khổ!
Có một số cách để lấy dữ liệu từ nhiều bảng trong cơ sở dữ liệu. Trong câu trả lời này, tôi sẽ sử dụng cú pháp nối ANSI-92. Điều này có thể khác với một số hướng dẫn khác ngoài đó sử dụng cú pháp ANSI-89 cũ hơn (và nếu bạn đã quen với 89, có vẻ ít trực quan hơn - nhưng tất cả những gì tôi có thể nói là thử nó) vì nó dễ hơn nhiều để hiểu khi các truy vấn bắt đầu trở nên phức tạp hơn. Tại sao sử dụng nó? Có đạt được hiệu suất? Các trả lời ngắn gọn là không, nhưng nó là dễ dàng hơn để đọc khi bạn đã quen với nó. Việc đọc các truy vấn được viết bởi những người khác sử dụng cú pháp này sẽ dễ dàng hơn.
Tôi cũng sẽ sử dụng khái niệm về một caryard nhỏ có cơ sở dữ liệu để theo dõi những chiếc xe có sẵn. Chủ sở hữu đã thuê bạn làm anh chàng Máy tính CNTT của anh ấy và hy vọng bạn có thể gửi cho anh ấy dữ liệu mà anh ấy yêu cầu khi thả mũ.
Tôi đã thực hiện một số bảng tra cứu sẽ được sử dụng bởi bảng cuối cùng. Điều này sẽ cho chúng ta một mô hình hợp lý để làm việc. Để bắt đầu, tôi sẽ chạy các truy vấn của mình dựa trên cơ sở dữ liệu mẫu có cấu trúc sau. Tôi sẽ cố gắng nghĩ về những lỗi phổ biến được tạo ra khi bắt đầu và giải thích những gì sai với chúng - cũng như tất nhiên chỉ ra cách sửa lỗi.
Bảng đầu tiên chỉ đơn giản là một danh sách màu sắc để chúng ta biết chúng ta có những màu gì trong sân xe.
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)
Bảng thương hiệu xác định các nhãn hiệu khác nhau của những chiếc xe mà caryard có thể bán.
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)
Bảng mô hình sẽ bao gồm các loại xe khác nhau, sẽ đơn giản hơn cho việc sử dụng các loại xe khác nhau hơn là các mẫu xe thực tế.
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)
Và cuối cùng, để buộc tất cả các bảng khác, bảng liên kết mọi thứ lại với nhau. Trường ID thực sự là số lô duy nhất được sử dụng để xác định ô tô.
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)
Điều này sẽ cung cấp cho chúng tôi đủ dữ liệu (tôi hy vọng) để che đi các ví dụ dưới đây về các loại liên kết khác nhau và cũng cung cấp đủ dữ liệu để làm cho chúng có giá trị.
Vì vậy, nhận được sự quan tâm của nó, ông chủ muốn biết ID của tất cả những chiếc xe thể thao mà ông có .
Đây là một hai bảng đơn giản tham gia. Chúng tôi có một bảng xác định mô hình và bảng có cổ phiếu có sẵn trong đó. Như bạn có thể thấy, dữ liệu trong model
cột của cars
bảng liên quan đến models
cột của cars
bảng chúng ta có. Bây giờ, chúng ta biết rằng các mô hình bảng có ID của 1
cho Sports
nên cho phép viết tham gia.
select
ID,
model
from
cars
join models
on model=ID
Vì vậy, truy vấn này có vẻ tốt phải không? Chúng tôi đã xác định hai bảng và chứa thông tin chúng tôi cần và sử dụng phép nối xác định chính xác cột nào sẽ tham gia.
ERROR 1052 (23000): Column 'ID' in field list is ambiguous
Ôi không! Một lỗi trong truy vấn đầu tiên của chúng tôi! Vâng, và nó là một quả mận. Bạn thấy đấy, truy vấn thực sự đã có đúng cột, nhưng một số trong số chúng tồn tại trong cả hai bảng, vì vậy cơ sở dữ liệu bị nhầm lẫn về cột thực tế chúng ta muốn nói là gì và ở đâu. Có hai giải pháp để giải quyết điều này. Đầu tiên là tốt đẹp và đơn giản, chúng ta có thể sử dụng tableName.columnName
để nói với cơ sở dữ liệu chính xác những gì chúng ta muốn nói, như thế này:
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)
Cái khác có lẽ thường được sử dụng hơn và được gọi là răng cưa bảng. Các bảng trong ví dụ này có các tên đơn giản và ngắn gọn, nhưng gõ một cái gì đó giống như KPI_DAILY_SALES_BY_DEPARTMENT
có thể sẽ nhanh chóng bị cũ, vì vậy một cách đơn giản là đặt biệt danh cho bảng như thế này:
select
a.ID,
b.model
from
cars a
join models b
on a.model=b.ID
Bây giờ, trở lại yêu cầu. Như bạn có thể thấy chúng tôi có thông tin chúng tôi cần, nhưng chúng tôi cũng có thông tin không được yêu cầu, vì vậy chúng tôi cần bao gồm một mệnh đề where trong tuyên bố để chỉ nhận được những chiếc xe Thể thao như đã hỏi. Vì tôi thích phương thức bí danh bảng hơn là sử dụng tên bảng nhiều lần, tôi sẽ sử dụng nó từ thời điểm này trở đi.
Rõ ràng, chúng ta cần thêm một mệnh đề where vào truy vấn của chúng tôi. Chúng tôi có thể xác định xe thể thao bằng ID=1
hoặc model='Sports'
. Vì ID được lập chỉ mục và khóa chính (và nó sẽ ít gõ hơn), hãy sử dụng nó trong truy vấn của chúng tôi.
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)
Chơi lô tô! Sếp vui lắm. Tất nhiên, là một ông chủ và không bao giờ hài lòng với những gì anh ta yêu cầu, anh ta xem thông tin, sau đó nói rằng tôi cũng muốn màu sắc .
Được rồi, vì vậy chúng tôi có một phần tốt của truy vấn của chúng tôi đã được viết, nhưng chúng tôi cần sử dụng bảng thứ ba là màu sắc. Bây giờ, bảng thông tin chính của chúng tôi cars
lưu ID màu xe và liên kết này trở lại cột ID màu. Vì vậy, theo cách tương tự như bản gốc, chúng ta có thể tham gia bảng thứ ba:
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)
Chết tiệt, mặc dù bảng đã được nối chính xác và các cột liên quan được liên kết, chúng tôi đã quên lấy thông tin thực tế từ bảng mới mà chúng tôi vừa liên kết.
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)
Phải, đó là ông chủ ra khỏi lưng chúng tôi một lát. Bây giờ, để giải thích một số điều này chi tiết hơn một chút. Như bạn có thể thấy, from
mệnh đề trong câu lệnh của chúng tôi liên kết bảng chính của chúng tôi (tôi thường sử dụng bảng chứa thông tin thay vì bảng tra cứu hoặc bảng thứ nguyên. Truy vấn sẽ hoạt động tốt với tất cả các bảng được chuyển đổi, nhưng ít có ý nghĩa hơn khi Chúng tôi quay lại truy vấn này để đọc nó trong một vài tháng, vì vậy tốt nhất là cố gắng viết một truy vấn sẽ hay và dễ hiểu - đặt nó ra một cách trực giác, sử dụng thụt lề tốt để mọi thứ rõ ràng như Nếu bạn tiếp tục dạy người khác, hãy cố gắng thấm nhuần những đặc điểm này trong các truy vấn của họ - đặc biệt nếu bạn sẽ khắc phục sự cố cho họ.
Hoàn toàn có thể tiếp tục liên kết nhiều bảng hơn theo cách này.
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
Trong khi tôi quên bao gồm một bảng nơi chúng tôi có thể muốn tham gia nhiều hơn một cột trong join
tuyên bố, đây là một ví dụ. Nếu models
bảng có các mô hình dành riêng cho thương hiệu và do đó cũng có một cột được gọi là brand
liên kết ngược với brands
bảng trên ID
trường, thì có thể thực hiện như sau:
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
Bạn có thể thấy, truy vấn ở trên không chỉ liên kết các bảng đã tham gia với bảng chính cars
mà còn chỉ định các phép nối giữa các bảng đã tham gia. Nếu điều này không được thực hiện, kết quả được gọi là tham gia cartesian - đó là dba nói xấu. Tham gia cartesian là một trong đó các hàng được trả về vì thông tin không cho cơ sở dữ liệu biết cách giới hạn kết quả, vì vậy truy vấn trả về tất cả các hàng phù hợp với tiêu chí.
Vì vậy, để đưa ra một ví dụ về tham gia cartesian, hãy chạy truy vấn sau:
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)
Chúa ơi, thật là xấu xí. Tuy nhiên, theo như cơ sở dữ liệu, đó chính xác là những gì được yêu cầu. Trong truy vấn, chúng tôi đã yêu cầu ID
từ cars
và model
từ models
. Tuy nhiên, vì chúng tôi không chỉ định cách tham gia các bảng, cơ sở dữ liệu đã khớp mọi hàng từ bảng đầu tiên với mọi hàng từ bảng thứ hai.
Được rồi, vì vậy ông chủ đã trở lại, và ông muốn biết thêm thông tin một lần nữa. Tôi muốn cùng một danh sách, nhưng cũng bao gồm 4WD trong đó .
Tuy nhiên, điều này cho chúng ta một cái cớ tuyệt vời để xem xét hai cách khác nhau để thực hiện điều này. Chúng ta có thể thêm một điều kiện khác vào mệnh đề where như thế này:
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
Mặc dù ở trên sẽ hoạt động hoàn hảo, nhưng hãy nhìn nó khác đi, đây là một lý do tuyệt vời để chỉ ra cách union
truy vấn sẽ hoạt động .
Chúng tôi biết rằng sau đây sẽ trả lại tất cả các xe thể thao:
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
Và sau đây sẽ trả về tất cả các 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
Vì vậy, bằng cách thêm một union all
mệnh đề giữa chúng, kết quả của truy vấn thứ hai sẽ được thêm vào kết quả của truy vấn đầu tiên.
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)
Như bạn có thể thấy, kết quả của truy vấn đầu tiên được trả về trước, tiếp theo là kết quả của truy vấn thứ hai.
Trong ví dụ này, tất nhiên sẽ dễ dàng hơn nhiều khi chỉ cần sử dụng truy vấn đầu tiên, nhưng union
các truy vấn có thể tuyệt vời cho các trường hợp cụ thể. Chúng là một cách tuyệt vời để trả về kết quả cụ thể từ các bảng từ các bảng không dễ dàng kết hợp với nhau - hoặc hoàn toàn là vấn đề không liên quan đến các bảng. Có một vài quy tắc để làm theo tuy nhiên.
- Các loại cột từ truy vấn đầu tiên phải khớp với các loại cột từ mọi truy vấn khác bên dưới.
- Tên của các cột từ truy vấn đầu tiên sẽ được sử dụng để xác định toàn bộ tập hợp kết quả.
- Số lượng cột trong mỗi truy vấn phải giống nhau.
Bây giờ, bạn có thể tự hỏi sự khác biệt giữa việc sử dụng union
và union all
. Một union
truy vấn sẽ loại bỏ trùng lặp, trong khi một truy vấn union all
sẽ không. Điều này không có nghĩa là có một hiệu suất nhỏ khi sử dụng union
hơnunion all
nhưng kết quả có thể được giá trị nó - Tôi sẽ không suy đoán trên đó đại loại như vậy trong mặc dù điều này.
Về lưu ý này, có thể đáng chú ý một số ghi chú bổ sung ở đây.
- Nếu chúng tôi muốn đặt hàng kết quả, chúng tôi có thể sử dụng
order by
nhưng bạn không thể sử dụng bí danh nữa. Trong truy vấn trên, việc nối thêm order by a.ID
sẽ dẫn đến lỗi - theo như kết quả có liên quan, cột được gọi ID
chứ không phải làa.ID
- mặc dù cùng một bí danh đã được sử dụng trong cả hai truy vấn.
- Chúng ta chỉ có thể có một
order by
tuyên bố, và nó phải là tuyên bố cuối cùng.
Đối với các ví dụ tiếp theo, tôi sẽ thêm một vài hàng vào bảng của chúng tôi.
Tôi đã thêm vào Holden
bảng thương hiệu. Tôi cũng đã thêm một hàng vào cars
có color
giá trị 12
- không có tham chiếu trong bảng màu.
Được rồi, ông chủ đã trở lại một lần nữa, sủa yêu cầu - * Tôi muốn đếm từng thương hiệu chúng tôi mang theo và số lượng xe trong đó! `- Điển hình, chúng tôi chỉ cần đến một phần thú vị của cuộc thảo luận của chúng tôi và ông chủ muốn làm việc nhiều hơn .
Rightyo, vì vậy điều đầu tiên chúng ta cần làm là có được một danh sách đầy đủ các thương hiệu có thể.
select
a.brand
from
brands a
+--------+
| brand |
+--------+
| Ford |
| Toyota |
| Nissan |
| Smart |
| BMW |
| Holden |
+--------+
6 rows in set (0.00 sec)
Bây giờ, khi chúng ta tham gia vào bảng ô tô của mình, chúng ta sẽ nhận được kết quả như sau:
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)
Tất nhiên đó là một vấn đề - chúng tôi không thấy bất kỳ đề cập nào về Holden
thương hiệu đáng yêu mà tôi đã thêm.
Điều này là do một phép nối tìm các hàng khớp trong cả hai bảng. Vì không có dữ liệu trong xe ô tô thuộc loại Holden
nào nên nó không được trả lại. Đây là nơi chúng ta có thể sử dụng một outer
tham gia. Điều này sẽ trả về tất cả các kết quả từ một bảng cho dù chúng có khớp với bảng khác hay không:
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)
Bây giờ chúng ta đã có điều đó, chúng ta có thể thêm một hàm tổng hợp đáng yêu để đếm và đưa ông chủ ra khỏi lưng trong giây lát.
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)
Và với điều đó, đi các ông chủ skulks.
Bây giờ, để giải thích điều này chi tiết hơn, các phép nối ngoài có thể là left
hoặc right
kiểu. Trái hoặc Phải xác định bảng nào được bao gồm đầy đủ . A left outer join
sẽ bao gồm tất cả các hàng từ bảng bên trái, trong khi (bạn đoán nó) aright outer join
mang tất cả các kết quả từ bảng bên phải vào kết quả.
Một số cơ sở dữ liệu sẽ cho phép một full outer join
kết quả sẽ mang lại kết quả (dù có khớp hay không) từ cả hai bảng, nhưng điều này không được hỗ trợ trong tất cả các cơ sở dữ liệu.
Bây giờ, tôi có thể tính đến thời điểm này, bạn đang tự hỏi liệu bạn có thể hợp nhất các loại tham gia trong một truy vấn hay không - và câu trả lời là có, bạn hoàn toàn có thể.
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)
Vì vậy, tại sao đó không phải là kết quả đã được mong đợi? Đó là bởi vì mặc dù chúng tôi đã chọn phép nối ngoài từ ô tô đến nhãn hiệu, nhưng nó không được chỉ định trong phép nối với màu sắc - vì vậy phép nối cụ thể đó sẽ chỉ mang lại kết quả khớp với cả hai bảng.
Đây là truy vấn sẽ hoạt động để có được kết quả mà chúng tôi mong đợi:
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)
Như chúng ta có thể thấy, chúng ta có hai phép nối ngoài trong truy vấn và kết quả sẽ đạt được như mong đợi.
Bây giờ, làm thế nào về những loại tham gia khác mà bạn yêu cầu? Còn giao lộ thì sao?
Chà, không phải tất cả các cơ sở dữ liệu đều hỗ trợ intersection
nhưng hầu như tất cả các cơ sở dữ liệu sẽ cho phép bạn tạo một giao điểm thông qua một phép nối (hoặc ít nhất là có cấu trúc trong đó câu lệnh).
Giao lộ là một loại tham gia hơi giống với union
mô tả ở trên - nhưng sự khác biệt là nó chỉ trả về các hàng dữ liệu giống hệt nhau (và tôi có nghĩa là giống hệt nhau) giữa các truy vấn riêng lẻ được liên kết bởi liên kết. Chỉ các hàng giống hệt nhau trong mọi vấn đề sẽ được trả lại.
Một ví dụ đơn giản sẽ là như vậy:
select
*
from
colors
where
ID>2
intersect
select
*
from
colors
where
id<4
Trong khi một union
truy vấn bình thường sẽ trả về tất cả các hàng của bảng (truy vấn đầu tiên trả về bất cứ thứ gì ID>2
và thứ hai có bất kỳ thứ gì ID<4
) sẽ dẫn đến một bộ đầy đủ, một truy vấn giao nhau sẽ chỉ trả về hàng khớp id=3
khi nó đáp ứng cả hai tiêu chí.
Bây giờ, nếu cơ sở dữ liệu của bạn không hỗ trợ intersect
truy vấn, phần trên có thể dễ dàng được cung cấp với truy vấn sau:
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)
Nếu bạn muốn thực hiện một giao lộ qua hai bảng khác nhau bằng cơ sở dữ liệu vốn không hỗ trợ truy vấn giao nhau, bạn sẽ cần tạo một liên kết trên mỗi cột của các bảng.