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_idfirst_namelast_namemanager_iddepartmentsalary
1JohnDoeNULLSales1500000
2JaneSmith1Marketing1700000
3BobJohnson1Sales1300000
4AliceBrown2HR2000000
5CharlieGreen2Marketing1800000

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:

shell
SELECT A.column1, B.column2, ...
FROM table_name AS A
JOIN table_name AS B ON A.common_column = B.common_column;
  • AB: Là các bí danh cho cùng một bảng table_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_idemployee_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ọ

shell
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ả:

EmployeeManager
JohnNULL
JaneJohn
BobJohn
AliceJane
CharlieJane

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ý

shell
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 1Employee 2Manager
JaneBobJohn
BobJaneJohn
AliceCharlieJane
CharlieAliceJane

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_idNULL).

Ví dụ 3: Tìm tất cả các nhân viên không có người quản lý

shell
SELECT first_name, last_name
FROM employees
WHERE manager_id IS NULL;

Kết quả:

first_namelast_name
JohnDoe

John là nhân viên duy nhất không có người quản lý (giá trị manager_idNULL).

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ọ

shell
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ọ

shell
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

shell
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!