> For the complete documentation index, see [llms.txt](https://learnsql.gitbook.io/lernmysql/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://learnsql.gitbook.io/lernmysql/welcome-to-the-mysql-tutorial/cau-lenh-join.md).

# Câu lệnh JOIN

**Kết và khoá**

Đôi khi chúng ta phải lấy dữ liệu từ hai bảng cùng một lúc, chúng ta thực hiện một kết nối.

Các bảng trong CSDL có thể quan hệ ràng buộc với nhau thông qua các khoá. Một khoá chính (primary key)  là một cột mà trong đó mỗi giá trị của hàng phải là duy nhất. Mục đích của khoá là kết nối dữ liệu lại với nhau, từ nhiều bảng khác nhau mà không gây trùng lắp dữ liệu giữa các bảng.

Trong bảng **Employees** (nhân viên) ở ví dụ dưới đây có cột **Employees\_ID** là khoá chính, bảo đảm rằng không thể có hai dòng nào có trùng **Employees\_ID**. **Employees\_ID** dùng để phân biệt hai nhân viên khi họ trùng tên.

Trong ví dụ dưới đây:

* **Employee\_ID** là khoá chính của bảng **Employees**.
* **Prod\_ID** là khoá chính của bảng **Orders**.
* Cột **Employeed\_ID** trong bảng **Orders** được sử dụng để kết nối với bảng **Employees**, chỉ đến nhân viên trong bảng **Employees**.

**Bảng Employees:**

| Employees\_ID | Name              |
| ------------- | ----------------- |
| 01            | Hansen, Ola       |
| 02            | Svendson, Tove    |
| 03            | Svendson, Stephen |
| 04            | Pettersen, Kari   |

**Bảng Orders:**

| Prod\_ID | Product | Employee\_ID |
| -------- | ------- | ------------ |
| 234      | Printer | 01           |
| 657      | Table   | 03           |
| 865      | Chair   | 03           |

**Kết nối hai bảng với nhau**

Chúng ta có thể lấy dữ liệu từ hai bảng bằng cách kết nối chúng, tương tự như sau:

**Ví dụ: Tìm xem ai đã đặt hàng sản phẩm và họ đã đặt món hàng gì:**

> `SELECT Employees.Name, Orders.Product`\
> `FROM Employees, Orders`\
> `WHERE Employees.Employee_ID = Orders.Employee_ID`

**kết quả trả về:**

| Name              | Product |
| ----------------- | ------- |
| Hansen, Ola       | Printer |
| Svendson, Stephen | Table   |
| Svendson, Stephen | Chair   |

**Ví dụ: Tìm xem ai đã đặt hàng máy in:**

> `SELECT Employees.Name`\
> `FROM Employees, Orders`\
> `WHERE Employees.Employee_ID = Orders.Employee_ID`\
> `AND Orders.Product = 'Printer'`

**kết quả trả về:**

| Name        |
| ----------- |
| Hansen, Ola |

**Sử dụng `JOIN`**

Ta có thể sử dụng từ khoá JOIN để kết nối dữ liệu từ hai bảng.

**Ví dụ: `INNER JOIN`**

**Cú pháp:**

> `SELECT cột_1, cột_2, cột_3`\
> `FROM bảng_1`\
> `INNER JOIN bảng_2`\
> `ON bảng_1.khoá_chính = bảng_2.khoá_ngoại`

**Ai đã đặt hàng và họ đã đặt món hàng nào:**

> `SELECT Employees.Name, Orders.Product`\
> `FROM Employees`\
> `INNER JOIN Orders`\
> `ON Employees.Employee_ID = Orders.Employee_ID`

`INNER JOIN` trả về tất cả các dòng ở cả hai bảng khi chúng tương ứng với nhau. Nếu có một dòng ở bảng **Employees** không ứng với dòng nào ở bảng **Orders**, dòng đó sẽ không được tính.

**kết quả trả về:**

| Name              | Product |
| ----------------- | ------- |
| Hansen, Ola       | Printer |
| Svendson, Stephen | Table   |
| Svendson, Stephen | Chair   |

**Ví dụ: `LEFT JOIN`**

**Cú pháp:**

> `SELECT cột_1, cột_2, cột_3`\
> `FROM bảng_1`\
> `LEFT JOIN bảng_2`\
> `ON bảng_1.khoá_chính = bảng_2.khoá_ngoại`

**Liệt kê tất cả các nhân viên và món hàng mà họ đặt (nếu có):**

> `SELECT Employees.Name, Orders.Product`\
> `FROM Employees`\
> `LEFT JOIN Orders`\
> `ON Employees.Employee_ID = Orders.Employee_ID`

`LEFT JOIN` trả về tất cả các dòng của bảng thứ nhất (**Employees**), ngay cả khi các dòng đó không ứng với dòng nào ở bảng thứ hai (**Orders**). Nếu có một dòng nào ở bảng **Employees** không ứng với bất cứ dòng nào ở bảng **Orders** thì dòng đó cũng vẫn được tính.

**kết quả trả về:**

| Name              | Product |
| ----------------- | ------- |
| Hansen, Ola       | Printer |
| Svendson, Tove    |         |
| Svendson, Stephen | Table   |
| Svendson, Stephen | Chair   |
| Pettersen, Kari   |         |

**Ví dụ: `RIGHT JOIN`**

**Cú pháp:**

> `SELECT cột_1, cột_2, cột_3`\
> `FROM bảng_1`\
> `RIGHT JOIN bảng_2`\
> `ON bảng_1.khoá_chính = bảng_2.khoá_ngoại`

**Liệt kê tất cả các mặt hàng được đặt và tên người đặt hàng (nếu có):**

> `SELECT Employees.Name, Orders.Product`\
> `FROM Employees`\
> `RIGHT JOIN Orders`\
> `ON Employees.Employee_ID = Orders.Employee_ID`

`RIGHT JOIN` trả về tất cả các dòng ở bảng thứ hai (**Orders**), ngay cả khi các dòng đó không ứng với dòng nào ở bảng thứ nhất (**Employees**). Nếu có một dòng nào ở bảng **Orders** không ứng với bất cứ dòng nào ở bảng **Employees** thì dòng đó cũng vẫn được tính.

**kết quả trả về:**

| Name              | Product |
| ----------------- | ------- |
| Hansen, Ola       | Printer |
| Svendson, Stephen | Table   |
| Svendson, Stephen | Chair   |

**Ví dụ: Ai đã đặt hàng máy in:**

> `SELECT Employees.Name`\
> `FROM Employees`\
> `INNER JOIN Orders`\
> `ON Employees.Employee_ID = Orders.Employee_ID`\
> `WHERE Orders.Product = 'Printer'`

**kết quả trả về:**

| Name        |
| ----------- |
| Hansen, Ola |
