1. Giới thiệu
Self Join là một kỹ thuật trong MySQL, trong đó một bảng được tự kết hợp với chính nó. Self Join thường được sử dụng khi bạn cần so sánh các hàng trong cùng một bảng hoặc tìm các mối quan hệ dựa trên các cột khác nhau trong cùng một bảng.
Mặc dù về cơ bản, Self Join không khác gì các loại JOIN khác, nhưng nó yêu cầu sử dụng bí danh (alias) cho bảng để phân biệt các phiên bản khác nhau của cùng một bảng khi thực hiện kết nối.
Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng MySQL Self Join với các ví dụ minh họa cụ thể từ một bảng dữ liệu giả định.
2. Bảng dữ liệu giả định
Giả sử chúng ta có bảng employees với các thông tin về nhân viên và cấp trên (người quản lý của họ) như sau:
| employee_id | first_name | last_name | manager_id | department | salary |
|---|---|---|---|---|---|
| 1 | John | Doe | NULL | Sales | 1500000 |
| 2 | Jane | Smith | 1 | Marketing | 1700000 |
| 3 | Bob | Johnson | 1 | Sales | 1300000 |
| 4 | Alice | Brown | 2 | HR | 2000000 |
| 5 | Charlie | Green | 2 | Marketing | 1800000 |
Trong bảng này:
employee_id: ID của nhân viên.manager_id: ID của người quản lý (là một nhân viên khác trong cùng bảng).department: Phòng ban mà nhân viên đang làm việc.salary: Mức lương của nhân viên.
3. SQL Self Join là gì?
SQL Self Join là quá trình kết hợp một bảng với chính nó bằng cách sử dụng các bí danh (aliases) để phân biệt giữa "phiên bản" gốc của bảng và phiên bản "kết nối" của bảng.
Cú pháp của Self Join thường sử dụng INNER JOIN hoặc LEFT JOIN với điều kiện ON, kết hợp cột trong bảng với chính nó.
Cú pháp của SQL Self Join:
SELECT A.column1, B.column2, ...
FROM table_name AS A
JOIN table_name AS B ON A.common_column = B.common_column;AvàB: Là các bí danh cho cùng một bảngtable_name.common_column: Là cột chung mà bạn muốn kết nối (trong ví dụ này có thể làmanager_idvàemployee_id).
4. Cách sử dụng SQL Self Join
a. Liệt kê tất cả các nhân viên và người quản lý của họ
Self Join thường được sử dụng để lấy thông tin về các mối quan hệ như giữa nhân viên và người quản lý của họ.
Ví dụ 1: Tìm tất cả các nhân viên cùng với tên người quản lý của họ
SELECT e.first_name AS 'Employee', m.first_name AS 'Manager'
FROM employees AS e
LEFT JOIN employees AS m ON e.manager_id = m.employee_id;Kết quả:
| Employee | Manager |
|---|---|
| John | NULL |
| Jane | John |
| Bob | John |
| Alice | Jane |
| Charlie | Jane |
Trong ví dụ này, bảng employees được tự kết hợp (Self Join) để tìm ra tên của người quản lý (manager_id) cho mỗi nhân viên (employee_id). John không có người quản lý nên giá trị Manager sẽ là NULL.
b. Tìm các nhân viên có cùng quản lý
Self Join có thể được sử dụng để tìm ra các nhân viên có cùng người quản lý.
Ví dụ 2: Tìm tất cả các cặp nhân viên có cùng người quản lý
SELECT e1.first_name AS 'Employee 1', e2.first_name AS 'Employee 2', m.first_name AS 'Manager'
FROM employees AS e1
JOIN employees AS e2 ON e1.manager_id = e2.manager_id
JOIN employees AS m ON e1.manager_id = m.employee_id
WHERE e1.employee_id <> e2.employee_id;Kết quả:
| Employee 1 | Employee 2 | Manager |
|---|---|---|
| Jane | Bob | John |
| Bob | Jane | John |
| Alice | Charlie | Jane |
| Charlie | Alice | Jane |
Trong ví dụ này, chúng ta sử dụng Self Join để so sánh các nhân viên có cùng manager_id, và kết hợp với bảng employees để lấy tên của người quản lý (Manager). Điều kiện WHERE e1.employee_id <> e2.employee_id giúp loại bỏ các cặp nhân viên giống nhau.
c. Tìm tất cả các nhân viên không có người quản lý
Self Join cũng có thể được sử dụng để tìm các nhân viên không có người quản lý (tức là giá trị manager_id là NULL).
Ví dụ 3: Tìm tất cả các nhân viên không có người quản lý
SELECT first_name, last_name
FROM employees
WHERE manager_id IS NULL;Kết quả:
| first_name | last_name |
|---|---|
| John | Doe |
John là nhân viên duy nhất không có người quản lý (giá trị manager_id là NULL).
5. Các ví dụ khác về MySQL Self Join
Ví dụ 1: Liệt kê tất cả nhân viên và phòng ban của người quản lý của họ
SELECT e.first_name AS 'Employee', e.department AS 'Employee Department', m.first_name AS 'Manager', m.department AS 'Manager Department'
FROM employees AS e
LEFT JOIN employees AS m ON e.manager_id = m.employee_id;Ví dụ 2: Tìm tất cả các nhân viên có lương cao hơn người quản lý của họ
SELECT e.first_name AS 'Employee', e.salary AS 'Employee Salary', m.first_name AS 'Manager', m.salary AS 'Manager Salary'
FROM employees AS e
JOIN employees AS m ON e.manager_id = m.employee_id
WHERE e.salary > m.salary;Ví dụ 3: Tìm tất cả các nhân viên có cùng người quản lý và cùng làm việc trong cùng một phòng ban
SELECT e1.first_name AS 'Employee 1', e2.first_name AS 'Employee 2', m.first_name AS 'Manager', e1.department AS 'Department'
FROM employees AS e1
JOIN employees AS e2 ON e1.manager_id = e2.manager_id AND e1.department = e2.department
JOIN employees AS m ON e1.manager_id = m.employee_id
WHERE e1.employee_id <> e2.employee_id;6. Một số lưu ý khi sử dụng MySQL Self Join
a. Sử dụng bí danh để phân biệt các bảng
Khi sử dụng Self Join, bạn phải sử dụng các bí danh (aliases) để phân biệt giữa hai phiên bản của cùng một bảng. Điều này là cần thiết để SQL có thể hiểu rõ bạn đang thao tác trên các phần khác nhau của cùng một bảng.
b. Cẩn thận với các điều kiện lọc (WHERE)
Khi sử dụng Self Join, bạn có thể cần thêm các điều kiện lọc, chẳng hạn như WHERE e1.employee_id <> e2.employee_id, để tránh việc kết hợp một hàng với chính nó và tạo ra các kết quả không mong muốn.
c. Hiệu suất
Self Join có thể ảnh hưởng đến hiệu suất khi làm việc với các bảng lớn, đặc biệt nếu không có chỉ mục (index) được tạo trên các cột được so sánh trong Self Join. Do đó, bạn nên tối ưu hóa truy vấn của mình bằng cách sử dụng chỉ mục.
Kết luận
SQL Self Join là một công cụ mạnh mẽ và hữu ích khi bạn cần so sánh các hàng trong cùng một bảng hoặc tìm kiếm các mối quan hệ phức tạp. Bằng cách sử dụng Self Join, bạn có thể giải quyết nhiều vấn đề thực tế như tìm các nhân viên có cùng người quản lý, so sánh lương giữa các nhân viên và người quản lý, và nhiều trường hợp khác.
Hãy thử áp dụng các ví dụ này trong các bài tập và dự án thực tế trên CodeTutHub để thành thạo hơn về cách sử dụng SQL Self Join trong MySQL!








