Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Truy vấn SQL trả về dữ liệu từ nhiều bảng

Phần 1 - Gia nhập và Liên hiệp

Câu trả lời này bao gồm:

  1. Phần 1
  2. Phần 2
    • Truy vấn phụ - chúng là gì, chúng có thể được sử dụng ở đâu và điều gì cần chú ý
    • Descartes tham gia AKA - Ôi, thật khốn nạn!

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 sử dụng cú pháp ANSI-89 cũ hơn (và nếu bạn đã quen với 89, có vẻ kém trực quan hơn nhiều - nhưng tất cả những gì tôi có thể nói là hãy thử) vì nó là nhiều dễ hiểu hơn khi các truy vấn bắt đầu phức tạp hơn. Tại sao sử dụng nó? Có tăng hiệu suất không? câu trả lời ngắn gọn là không, nhưng nó dễ đọc hơn khi bạn đã quen với nó. Việc đọc các truy vấn do những người khác viết bằ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 chiếc caryard nhỏ có cơ sở dữ liệu để theo dõi những chiếc xe nào nó có sẵn. Chủ sở hữu đã thuê bạn làm nhân viên Máy tính CNTT của họ và mong muốn bạn có thể cung cấp cho anh ta dữ liệu mà anh ta yêu cầu chỉ bằng một cú đánh rơi.

Tôi đã lập 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ẽ cung cấp cho chúng tôi 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 sai lầm phổ biến thường mắc phải khi bắt đầu và giải thích điều gì sai với chúng - cũng như tất nhiên là chỉ ra cách sửa chúng.

Bảng đầu tiên chỉ đơn giản là bảng liệt kê màu sắc để chúng ta biết chúng ta có những màu gì trong bãi 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 nhãn hiệu xác định các nhãn hiệu khác nhau của những chiếc ô tô mà caryard có thể bán được.

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 ô tô khác nhau, sẽ đơn giản hơn nếu sử dụng các loại ô tô khác nhau hơn là các mô hình ô tô 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ả những chiếc bàn khác này lại, chiếc bàn gắ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 để nhận dạng ô 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) để bao quát các ví dụ bên dưới 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 đáng giá.

Vì vậy, đi sâu vào vấn đề, ông chủ muốn biết ID của tất cả những chiếc xe thể thao mà ông ta có .

Đây là một tham gia hai bảng đơn giản. Chúng tôi có một bảng xác định mô hình và bảng có sẵn hàng 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 tôi có. Bây giờ, chúng ta biết rằng bảng mô hình có ID là 1 cho Sports vì vậy chúng ta hãy 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 một phép nối xác định chính xác những cột nào để tham gia.

ERROR 1052 (23000): Column 'ID' in field list is ambiguous

Ôi không! Đã xảy ra 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ó các cột phù hợp, 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ế mà chúng tôi muốn nói đến và ở đâu. Có hai giải pháp để giải quyết vấn đề này. Đầu tiên là tốt và đơn giản, chúng ta có thể sử dụng tableName.columnName để cho cơ sở dữ liệu biết chính xác ý của chúng tô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)

Loại còn lại có lẽ thường được sử dụng hơn và được gọi là bí danh bảng. Các bảng trong ví dụ này có tên đơn giản và đẹp, nhưng gõ ra một cái gì đó như KPI_DAILY_SALES_BY_DEPARTMENT có lẽ sẽ già đi nhanh chóng, vì vậy một cách đơn giản là đặt tên cho bảng như sau:

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 đưa điều khoản where trong tuyên bố để chỉ nhận được những chiếc xe Thể thao như đã được yêu cầu. Vì tôi thích phương pháp bí danh bảng hơn là sử dụng lặp đi lặp lại các tên bảng, nên tôi sẽ giữ nó từ thời điểm này trở đi.

Rõ ràng, chúng ta cần thêm mệnh đề where vào truy vấn của mình. 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ó xảy ra để gõ ít hơn), hãy sử dụng ID đó 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ô! Ông chủ vui vẻ. Tất nhiên, là một ông chủ và không bao giờ hài lòng với những gì mình yêu cầu, anh ta xem thông tin, sau đó nói Tôi cũng muốn màu sắc .

Được rồi, vậy là chúng ta đã viết sẵn một phần truy vấn của mình, nhưng chúng ta cần sử dụng bảng thứ ba là các màu. Bây giờ, bảng thông tin chính của chúng ta cars lưu trữ ID màu xe và điều này liên kết 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ể nối một 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 có liên quan được liên kết, chúng tôi đã quên kéo thông tin thực tế vào 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)

Đúng vậy, đó là ông chủ đang quay lưng lại với chúng ta trong giây 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 hơn là bảng tra cứu hoặc bảng thứ nguyên. Truy vấn sẽ hoạt động tốt với các bảng được chuyển đổi xung quanh, nhưng sẽ kém ý nghĩa hơn khi chúng tôi quay lại truy vấn này để đọc nó trong thời gian vài tháng, vì vậy, tốt nhất là cố gắng viết một truy vấn sao cho hay và dễ hiểu - trình bày nó một cách trực quan, sử dụng cách thụt lề dễ hiểu để mọi thứ rõ ràng nhất có thể. Nếu bạn tiếp tục dạy những người khác, cố gắng đưa những đặc điểm này vào truy vấn của họ - đặc biệt nếu bạn sẽ gỡ rối chúng.

Hoàn toàn có thể tiếp tục liên kết ngày càng nhiều bảng 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

Mặc dù tôi đã quên bao gồm một bảng mà chúng tôi có thể muốn nối nhiều cột trong join đâ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 lại với brand trên ID , nó có thể được 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 đã nối với cars chính mà còn chỉ định các phép nối giữa các bảng đã được nối. Nếu điều này không được thực hiện, kết quả được gọi là liên kết cacte - đó là tiếng dba nói xấu. Một phép nối cacte 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ề phép nối cacte, 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)

Lạy chúa, thật là xấu xí. Tuy nhiên, theo như cơ sở dữ liệu có liên quan, nó chính xác những gì đã được yêu cầu. Trong truy vấn, chúng tôi đã yêu cầu cung cấp ID từ carsmodel từ các mô hình models . Tuy nhiên, vì chúng tôi không chỉ định cách thức để nối các bảng, cơ sở dữ liệu đã khớp với 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ậy là ông chủ đã trở lại và ông ấy muốn biết thêm thông tin. Tôi muốn có cùng một danh sách nhưng cũng bao gồm cả 4 người khuyết tật trong đó .

Tuy nhiên, điều này cho chúng ta một lý do 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ù những điều trên sẽ hoạt động hoàn toàn tốt, nhưng chúng ta hãy nhìn vào nó theo cách khác, đây là một lý do tuyệt vời để chỉ ra cách một union truy vấn sẽ hoạt động.

Chúng tôi biết rằng những điều sau đây sẽ trả về 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à phần sau sẽ trả về tất 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 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ề đầu tiên, sau đó 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 nếu chỉ sử dụng truy vấn đầu tiên, nhưng union các truy vấn có thể rất tốt 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ễ kết hợp với nhau - hoặc đối với vấn đề đó là hoàn toàn các bảng không liên quan. Tuy nhiên, có một số quy tắc cần tuân theo.

  • 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ể đang tự hỏi điều gì sự khác biệt giữa việc sử dụng unionunion all . Một union truy vấn sẽ loại bỏ các bản sao, trong khi một union all sẽ không. Điều này có nghĩa là có một lần truy cập hiệu suất nhỏ khi sử dụng union over union all nhưng kết quả có thể xứng đáng - mặc dù vậy, tôi sẽ không suy đoán về những thứ như vậy trong việc này.

Trên ghi chú này, có thể cần lưu ý một số ghi chú bổ sung ở đây.

  • Nếu chúng tôi muốn sắp xếp 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, thêm một đơn đặt hàng order by a.ID sẽ dẫn đến lỗi - liên quan đến kết quả, cột được gọi là ID thay vì a.ID - mặc dù cùng một bí danh đã được sử dụng trong cả hai truy vấn.
  • Chúng tôi chỉ có thể có một order by và nó phải là câu lệnh 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 bổ sung vào bảng của chúng tôi.

Tôi đã thêm Holden vào bảng thương hiệu, tôi cũng đã thêm một hàng vào carscolor giá trị của 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, yêu cầu sủa - * Tôi muốn đếm từng nhãn hiệu chúng tôi mang theo và số lượng xe hơi trong đó! .

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ể có.

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 nối điều này với bảng ô tô của chúng ta, chúng ta nhận được kết quả 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 đến Holden đáng yêu thương hiệu tôi đã thêm.

Điều này là do một phép nối tìm kiếm các hàng phù hợp trong cả hai những cái bàn. Vì không có dữ liệu trong ô tô thuộc loại Holden nó không được trả lại. Đây là nơi chúng ta có thể sử dụng outer tham gia. Điều này sẽ trả về tất cả kết quả từ một bảng cho dù chúng có khớp với bảng kia 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à khiến ông chủ không quay 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à cùng với đó, ông chủ sẽ bị trượt chân.

Bây giờ, để giải thích điều này một cách chi tiết hơn, các phép nối bên ngoài có thể nằm ở left hoặc right gõ phím. Bên trái hoặc bên phải xác định bảng nào là đầy đủ bao gồm. Một 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ó) một right outer join đưa tất 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 điều này sẽ mang lại kết quả (cho dù phù hợ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ể đã đoán ra tại thời điểm này, bạn đang tự hỏi liệu bạn có thể hợp nhất các kiểu liên kết 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ể làm được.

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ả như mong đợi? Đó là bởi vì mặc dù chúng tôi đã chọn phép nối ngoài cùng từ ô tô đến thương hiệu, nhưng nó không được chỉ định trong phép nối theo màu sắc - vì vậy phép nối cụ thể đó sẽ chỉ mang lại kết quả phù hợp trong cả hai bảng.

Đây là truy vấn sẽ hoạt động để nhận đượ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 kết nối bên ngoài trong truy vấn và kết quả đang diễn ra như mong đợi.

Bây giờ, làm thế nào về những loại liên kết khác mà bạn yêu cầu? Còn về Giao lộ thì sao?

Chà, không phải tất cả cơ sở dữ liệu đều hỗ trợ intersection nhưng hầu hết 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âu lệnh where được cấu trúc tốt).

Giao lộ là một kiểu liên kết hơi giống với union như được 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 là giống hệt nhau) giữa các truy vấn riêng lẻ khác nhau được liên hợp tham gia. Chỉ các hàng giống hệt nhau về mọi mặt mới được trả về.

Một ví dụ đơn giản như sau:

select
    *
from
    colors
where
    ID>2
intersect
select
    *
from
    colors
where
    id<4

Trong khi một union bình thường truy vấn sẽ trả về tất cả các hàng của bảng (truy vấn đầu tiên trả về bất kỳ thứ gì qua ID>2 và bất cứ thứ gì thứ hai có ID<4 ) sẽ dẫn đến một tập hợp đầy đủ, một truy vấn giao nhau sẽ chỉ trả về hàng phù hợp với id=3 vì 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, bạn có thể dễ dàng thực hiện những điều trên 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 cắt trên hai bảng khác nhau bằng cách sử dụng cơ sở dữ liệu vốn dĩ không hỗ trợ truy vấn giao cắt, bạn sẽ cần tạo một liên kết trên mọi cột trong số các bảng.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để thêm chỉ mục vào bảng MySQL?

  2. Định dạng ngày MySQL - những điều bạn cần biết

  3. Chuyển đổi các ký tự latin1 trên bảng UTF8 thành UTF8

  4. Cho phép tất cả các kết nối từ xa, MySQL

  5. Cách kết nối nhiều cơ sở dữ liệu trong PHP, MYSQLi &PDO