Đại số quan hệ là gì?
Đại số quan hệ là một ngôn ngữ truy vấn thủ tục. Nó cho cơ sở dữ liệu biết cách truy xuất dữ liệu, không chỉ những gì bạn muốn.
Đó là điểm khác biệt then chốt với SQL, vốn là ngôn ngữ khai báo. Khi viết truy vấn SQL, bạn mô tả kết quả mong muốn. Đại số quan hệ mô tả chính xác chuỗi thao tác để đạt được kết quả đó.
Nó hoạt động trên các quan hệ — thuật ngữ hình thức cho bảng. Bạn đưa vào một hoặc nhiều quan hệ làm đầu vào, áp dụng một thao tác, và nhận lại một quan hệ làm đầu ra.
Phần cuối cùng đó chính là tính đóng. Dù bạn áp dụng thao tác nào — lọc hàng, chọn cột, kết hợp bảng — kết quả luôn là một quan hệ khác. Điều này quan trọng vì nó cho phép bạn xâu chuỗi các thao tác với nhau. Đầu ra của thao tác này trở thành đầu vào của thao tác tiếp theo, và bạn có thể chồng ghép chúng sâu bao nhiêu tùy ý.

Hãy hình dung đại số quan hệ như những khối xây dựng. Mỗi khối nhận một (hoặc hai) bảng, làm gì đó với nó, rồi trả lại một bảng. Các hệ quản trị cơ sở dữ liệu dùng những khối này bên trong để phân rã và thực thi truy vấn SQL của bạn.
Các khái niệm nền tảng trong đại số quan hệ
Trước khi làm việc với các toán tử đại số quan hệ, bạn cần nắm vững thuật ngữ. Tin tốt là chỉ có năm thuật ngữ cần nhớ.
-
Quan hệ (Relation) chính là một bảng. Nó có các hàng và cột, và biểu diễn một tập dữ liệu về một thực thể cụ thể — như nhân viên hoặc phòng ban. Trong đại số quan hệ, mọi thao tác đều nhận một hoặc nhiều quan hệ làm đầu vào và tạo ra một quan hệ làm đầu ra.
-
Bộ (Tuple) là một hàng đơn lẻ trong bảng đó. Nếu bảng
Employeescủa bạn có 10 hàng, thì nó có 10 bộ. Mỗi bộ đại diện cho một bản ghi — ở đây là một nhân viên. -
Thuộc tính (Attribute) là một cột. Bảng
Employeescó thể có các thuộc tính nhưemployee_id,namevàdepartment_id. Thuộc tính xác định loại dữ liệu mà mỗi bộ chứa. -
Bậc (Degree) là số lượng thuộc tính trong một quan hệ. Nếu
Employeescó năm cột, thì bậc của nó là 5. Điều này quan trọng khi bạn kết hợp các quan hệ — một số thao tác yêu cầu bậc phải khớp nhau. -
Lực lượng (Cardinality) là số lượng bộ trong một quan hệ. Nếu bảng
Employeescủa bạn có 200 hàng, thì lực lượng của nó là 200. Lực lượng thay đổi khi bạn thêm hoặc xóa hàng; bậc chỉ thay đổi khi bạn thêm hoặc xóa cột.
Dưới đây là cách các thuật ngữ này ánh xạ sang những gì bạn đã biết:

Đại số quan hệ so với thuật ngữ thông dụng
Hãy chắc rằng bạn nắm vững các khái niệm này, các toán tử sau đó sẽ trở nên hoàn toàn dễ hiểu.
Các thao tác đại số quan hệ cơ bản trong DBMS
Có năm toán tử nền tảng trong đại số quan hệ. Mọi thao tác khác — phép nối, giao, phép chia — đều được xây dựng từ năm toán tử này.
Để các ví dụ nhất quán, tôi sẽ dùng hai bảng xuyên suốt phần này:
Employees

Bảng Employees
Departments

Bảng Departments
Chọn (Selection) (σ)
Selection lọc các hàng dựa trên một điều kiện. Đây là tương đương trong đại số quan hệ với mệnh đề WHERE.
Ký hiệu như sau:
σ condition (Relation)
Giả sử bạn muốn tất cả nhân viên có lương trên 60.000:
σ salary > 60000 (Employees)
Kết quả là một quan hệ mới chỉ gồm các hàng khớp điều kiện — Alice và Carol. Cấu trúc bảng giữ nguyên, nên bạn chỉ loại bỏ các hàng không đáp ứng điều kiện.
Tương đương trong SQL:
SELECT * FROM Employees
WHERE salary > 60000;
Chiếu (Projection) (π)
Projection chọn các cột cụ thể từ một quan hệ và loại bỏ phần còn lại. Đây là cách bạn rút gọn bảng về những thuộc tính mình quan tâm.
π attribute1, attribute2 (Relation)
Để chỉ lấy tên và lương của tất cả nhân viên:
π name, salary (Employees)
Một điểm cần lưu ý là projection loại bỏ các hàng trùng lặp trong kết quả. Nếu hai bộ trở nên giống hệt nhau sau khi bạn bỏ các cột thừa, chỉ một bản sao được giữ lại trong đầu ra.
Tương đương trong SQL:
SELECT DISTINCT name, salary
FROM Employees;
Hợp (Union) (∪)
Union kết hợp hai quan hệ thành một, gộp toàn bộ các bộ của chúng. Các hàng trùng lặp được tự động loại bỏ.
Ký hiệu:
Relation1 ∪ Relation2
Điều kiện là cả hai quan hệ phải tương thích hợp (union-compatible). Nghĩa là chúng cần có cùng số thuộc tính và các thuộc tính tương ứng phải cùng kiểu dữ liệu. Bạn không thể hợp một bảng nhân viên với một bảng phòng ban vì lược đồ không khớp.
Giả sử bạn có bảng Contractors có cùng cấu trúc với Employees. Union sẽ cho bạn mọi người ở cả hai bảng, không trùng lặp:
Employees ∪ Contractors
Tương đương trong SQL:
SELECT * FROM Employees
UNION
SELECT * FROM Contractors;
Hiệu (Set difference) (−)
Set difference trả về các bộ tồn tại trong quan hệ thứ nhất nhưng không có trong quan hệ thứ hai. Hãy hình dung như phép trừ:
Relation1 − Relation2
Tương tự union, cả hai quan hệ phải tương thích hợp.
Nếu bạn muốn tất cả nhân viên không phải là nhà thầu, cú pháp sẽ là:
Employees − Contractors
Kết quả chỉ chứa những hàng từ Employees không có bản khớp trong Contractors.
Tương đương trong SQL:
SELECT * FROM Employees
EXCEPT
SELECT * FROM Contractors;
Tích Descartes (Cartesian product) (×)
Một tích Descartes kết hợp mọi bộ từ quan hệ thứ nhất với mọi bộ từ quan hệ thứ hai. Nếu Employees có 4 hàng và Departments có 3 hàng, kết quả có 4 × 3 = 12 hàng.
Employees × Departments
Tự thân, kết quả hiếm khi hữu ích — bạn nhận mọi tổ hợp có thể giữa nhân viên và phòng ban, bao gồm cả những cặp không liên quan nhau. Nhưng tích Descartes là nền tảng của phép nối. Bạn kết hợp nó với selection để chỉ giữ những hàng mà mối quan hệ có ý nghĩa.
Tương đương trong SQL:
SELECT * FROM Employees, Departments;
Năm toán tử này là nền móng. Mọi thứ khác trong đại số quan hệ là cách viết rút gọn khi kết hợp chúng.
Các phép nối trong đại số quan hệ
Phép nối là những thao tác được dùng nhiều nhất trong đại số quan hệ — và chúng không hề bí hiểm như vẻ ngoài.
Mọi phép nối chỉ là tích Descartes theo sau bởi selection. Bạn kết hợp tất cả các bộ từ hai quan hệ, rồi lọc bỏ những bộ không thỏa điều kiện. Phép nối tồn tại như một dạng viết tắt vì thực hiện tích Descartes đầy đủ trước là tốn kém. Join áp dụng điều kiện ngay trong quá trình kết hợp, giúp giảm kích thước kết quả trung gian.
Natural join (⋈)
Natural join tự động nối hai quan hệ trên tất cả thuộc tính trùng tên và chỉ giữ một bản sao của các cột chung đó trong kết quả:
Employees ⋈ Departments
Vì cả hai bảng đều có department_id, natural join sẽ ghép những hàng có giá trị đó bằng nhau và gộp chúng. Alice (department_id = 10) khớp với Engineering, Bob với Marketing, v.v.
Bạn không cần viết điều kiện — phép nối tự suy ra từ lược đồ. Điều đó tiện lợi, nhưng cũng có nghĩa là đổi tên cột có thể làm hỏng truy vấn của bạn.
Tương đương trong SQL:
SELECT * FROM Employees
NATURAL JOIN Departments;
Theta join (⋈θ)
Theta join nối hai quan hệ dựa trên bất kỳ điều kiện nào bạn chỉ định — điều kiện có thể dùng mọi toán tử so sánh: =, ≠, <, >, ≤, ≥.
Employees ⋈ salary > 60000 AND department_id = department_id Departments
Điều này cho bạn toàn quyền kiểm soát điều kiện nối. Phần lớn các phép nối bạn viết trong thực tế, ở tầng dưới, đều là theta join.
Tương đương trong SQL:
SELECT * FROM Employees, Departments
WHERE Employees.salary > 60000
AND Employees.department_id = Departments.department_id;
Equi join
Equi join là một theta join mà điều kiện chỉ dùng phép bằng (=). Đây là loại phổ biến nhất.
Employees ⋈ Employees.department_id = Departments.department_id Departments
Kết quả bao gồm tất cả các cột từ cả hai bảng, nghĩa là department_id xuất hiện hai lần. Đó là khác biệt chính với natural join — equi join không loại bỏ các cột trùng lặp.
Tương đương trong SQL:
SELECT * FROM Employees
INNER JOIN Departments
ON Employees.department_id = Departments.department_id;
Outer join
Các phép nối ở trên chỉ trả về những hàng có bản khớp ở cả hai quan hệ. Outer join giữ cả các hàng không khớp, điền NULL cho giá trị thiếu.
Có ba biến thể:
-
Left outer join (⟕) giữ tất cả các hàng từ quan hệ bên trái. Nếu một hàng trong
Employeeskhông có phòng ban khớp, nó vẫn xuất hiện trong kết quả vớiNULLở các cột phòng ban. -
Right outer join (⟖) giữ tất cả các hàng từ quan hệ bên phải. Các phòng ban không có nhân viên vẫn xuất hiện, với
NULLở các cột nhân viên. -
Full outer join (⟗) giữ tất cả các hàng từ cả hai quan hệ. Các hàng không khớp từ bất kỳ phía nào cũng xuất hiện với
NULLcho các giá trị thiếu.
Tương đương trong SQL:
-- Left outer join
SELECT * FROM Employees
LEFT JOIN Departments
ON Employees.department_id = Departments.department_id;
-- Right outer join
SELECT * FROM Employees
RIGHT JOIN Departments
ON Employees.department_id = Departments.department_id;
-- Full outer join
SELECT * FROM Employees
FULL OUTER JOIN Departments
ON Employees.department_id = Departments.department_id;
Hãy dùng outer join khi bạn không thể bỏ qua các hàng không có bản khớp — ví dụ khi bạn cần danh sách đầy đủ nhân viên bất kể phòng ban của họ có tồn tại trong hệ thống hay không.
Các toán tử đại số quan hệ dẫn xuất
Các toán tử dẫn xuất là lối tắt được xây dựng từ năm toán tử cơ bản đã trình bày trước đó.
Giao (Intersection) (∩)
Intersection chỉ trả về các bộ xuất hiện ở cả hai quan hệ. Giống như union và set difference, cả hai quan hệ phải tương thích hợp.
Employees ∩ Contractors
Nếu một nhân viên cũng là nhà thầu, họ sẽ xuất hiện trong kết quả. Những người khác bị loại.
Bên dưới, intersection chỉ là phép trừ tập hợp được áp dụng hai lần:
Employees ∩ Contractors = Employees − (Employees − Contractors)
Tương đương trong SQL:
SELECT * FROM Employees
INTERSECT
SELECT * FROM Contractors;
Chia (Division) (÷)
Division là toán tử làm khó nhiều sinh viên CNTT và người mới — nhưng khái niệm đơn giản hơn vẻ ngoài.
Division trả lời câu hỏi: "những bộ nào trong quan hệ A có liên hệ với tất cả các bộ trong quan hệ B?"
Giả sử bạn có bảng CourseEnrollments theo dõi sinh viên đăng ký những học phần nào, và bảng RequiredCourses liệt kê mọi học phần bắt buộc phải hoàn thành. Division cho bạn các sinh viên đăng ký tất cả các học phần bắt buộc.
CourseEnrollments ÷ RequiredCourses
Lý do khiến nó bị coi là khó: không có tương đương trực tiếp trong SQL. Để mô phỏng division trong SQL, bạn cần phủ định kép — "tìm các sinh viên mà không tồn tại học phần bắt buộc nào họ chưa học":
SELECT DISTINCT student_id FROM CourseEnrollments ce1
WHERE NOT EXISTS (
SELECT course_id FROM RequiredCourses rc
WHERE NOT EXISTS (
SELECT * FROM CourseEnrollments ce2
WHERE ce2.student_id = ce1.student_id
AND ce2.course_id = rc.course_id
)
);
Mẫu đôi NOT EXISTS đó là cách tiêu chuẩn để diễn đạt division trong SQL. Nếu bạn gặp câu hỏi phỏng vấn kiểu "tìm tất cả X liên quan đến mọi Y", thì division là toán tử nên nghĩ đến.
Đổi tên (Rename) (ρ)
Rename cho phép bạn đặt tên mới cho một quan hệ hoặc các thuộc tính của nó. Nó không thay đổi dữ liệu, chỉ thay đổi cách gọi tên.
ρ NewName (Relation)
Hoặc để đổi tên cả quan hệ lẫn các thuộc tính của nó:
ρ NewName(attr1, attr2, ...) (Relation)
Rename hữu ích khi bạn cần nối một bảng với chính nó — nếu không, tên thuộc tính sẽ xung đột và thao tác trở nên vô nghĩa. Nó cũng hữu ích khi xâu chuỗi các thao tác và bạn muốn các kết quả trung gian có tên có ý nghĩa.
Tương đương trong SQL:
SELECT * FROM Employees AS E1;
-- hoặc đổi tên cột:
SELECT employee_id AS id, name AS employee_name FROM Employees;
Ba toán tử này là những thứ bạn cần ghi nhớ. Giao và đổi tên thì dễ, còn phép chia là phần đáng để luyện tập trước bất kỳ kỳ thi hay buổi phỏng vấn cơ sở dữ liệu nào.
Đại số quan hệ so với SQL
SQL và đại số quan hệ không phải là một — nhưng SQL sẽ không tồn tại nếu thiếu nó.
Khác biệt cốt lõi nằm ở cách mỗi bên tư duy về truy vấn. Đại số quan hệ là thủ tục — bạn chỉ rõ chuỗi thao tác chính xác để lấy kết quả. SQL là khai báo — bạn mô tả kết quả mong muốn và hệ quản trị sẽ tự tìm cách để đạt được nó.
Lấy ví dụ đơn giản. Trong đại số quan hệ, truy xuất nhân viên thuộc Engineering trông như thế này:
π name, salary (σ department_id = 10 (Employees))
Bạn đang chỉ cho cơ sở dữ liệu chính xác cần làm gì: trước lọc hàng, rồi chọn cột. Thứ tự thao tác là tường minh.
Trong SQL, bạn viết:
SELECT name, salary
FROM Employees
WHERE department_id = 10;
Bạn đang mô tả kết quả mong muốn. Hệ quản trị dịch nó thành một chuỗi thao tác — và các thao tác nội bộ đó được xây dựng trên đại số quan hệ.
Đó là mối quan hệ giữa hai thứ. SQL là ngôn ngữ hướng người dùng; đại số quan hệ là mô hình lý thuyết bên dưới. Khi hệ quản trị nhận một truy vấn SQL, nó phân tách thành biểu diễn nội bộ dựa trên đại số quan hệ, tối ưu, rồi thực thi.
SQL cũng vượt xa những gì đại số quan hệ định nghĩa. Đại số quan hệ không có khái niệm về:
-
Tổng hợp —
SUM(),COUNT(),AVG() -
Nhóm —
GROUP BY -
Sắp xếp —
ORDER BY -
Xử lý trùng lặp — đại số quan hệ làm việc với tập hợp (không trùng lặp); SQL làm việc với đa tập (mặc định cho phép trùng lặp)
Những tính năng này được thêm vào SQL vì nhu cầu truy vấn thực tế. Nhưng chúng được xây dựng trên nền tảng đại số quan hệ.
Tóm lại, hiểu đại số quan hệ giúp bạn biết các truy vấn SQL được cấu trúc và biến đổi nội bộ ra sao. Nó sẽ không thay đổi cách bạn viết SQL hằng ngày, nhưng sẽ thay đổi cách bạn lý giải những gì truy vấn của mình thực sự làm.
Sai sót và nhầm lẫn thường gặp
Phần lớn nhầm lẫn với đại số quan hệ xoay quanh vài hiểu lầm lặp đi lặp lại. Hãy điểm qua chúng.
-
Xem SQL và đại số quan hệ là một. Chúng không phải vậy. SQL lấy cảm hứng từ đại số quan hệ, nhưng không thể hoán đổi cho nhau. SQL là khai báo và bao gồm các tính năng như tổng hợp và sắp xếp mà đại số quan hệ không định nghĩa. Đại số quan hệ là mô hình hình thức; SQL là ngôn ngữ thực tiễn xây trên nó.
-
Quên yêu cầu tương thích lược đồ. Union, intersection và set difference đều yêu cầu các quan hệ tương thích hợp — cùng số thuộc tính, cùng kiểu dữ liệu theo cùng thứ tự. Cố áp dụng các toán tử này cho bảng có lược đồ khác nhau sẽ không hiệu quả. Điều này gây nhầm lẫn vì phép nối không có yêu cầu như vậy.
-
Không hiểu toán tử chia. Chia là toán tử không có tương đương trực tiếp trong SQL, nên dễ gây khó. Nếu bạn thấy truy vấn yêu cầu "tìm tất cả X liên quan đến mọi Y", đó là division. Bản dịch sang SQL cần mẫu phủ định kép
NOT EXISTS— không hiển nhiên, nên đáng để luyện trước kỳ thi hay phỏng vấn. -
Nghĩ rằng join là toán tử độc lập. Chúng không phải là nguyên thủy. Mọi join là tích Descartes kết hợp với selection. Natural join, theta join, equi join — tất cả đều là rút gọn của tổ hợp đó. Hiểu điều này giúp bạn dự đoán hành vi join dễ hơn khi kết quả trông bất ngờ.
Kết luận
Đại số quan hệ là xương sống lý thuyết của mọi hệ cơ sở dữ liệu quan hệ. Mỗi truy vấn bạn viết trong SQL đều được dịch thành một chuỗi thao tác đại số quan hệ trước khi hệ quản trị chạm vào bất kỳ hàng dữ liệu nào.
Các toán tử — chọn, chiếu, hợp, hiệu, tích Descartes và các toán tử dẫn xuất — là những khối xây dựng của quá trình dịch đó. Khi hiểu cách chúng hoạt động và cách chúng xâu chuỗi, bạn sẽ không còn xem SQL như một hộp đen mà nhìn thấy cấu trúc bên dưới.
Giá trị thực sự của việc học đại số quan hệ là: hiểu các truy vấn của bạn thực sự đang làm gì, chứ không phải để viết chúng bằng ký pháp hình thức.

Câu hỏi thường gặp về Đại số quan hệ
Đại số quan hệ trong DBMS là gì?
Đại số quan hệ là một ngôn ngữ truy vấn hình thức định nghĩa cách dữ liệu có thể được truy xuất và thao tác trong cơ sở dữ liệu quan hệ. Nó hoạt động trên các quan hệ (bảng) và tạo ra một quan hệ mới làm đầu ra cho mỗi thao tác. Các hệ quản trị cơ sở dữ liệu dùng nó bên trong để phân rã và thực thi truy vấn SQL.
Các toán tử cơ bản trong đại số quan hệ là gì?
Năm toán tử nền tảng là chọn (σ), chiếu (π), hợp (∪), hiệu (−), và tích Descartes (×). Chọn lọc các hàng, chiếu chọn các cột, hợp kết hợp hai quan hệ tương thích, hiệu trừ các bộ, và tích Descartes kết hợp mọi bộ từ hai quan hệ. Mọi toán tử khác — join, giao, chia — đều dẫn xuất từ năm toán tử này.
Sự khác biệt giữa đại số quan hệ và SQL là gì?
Đại số quan hệ là thủ tục — nó chỉ rõ chuỗi thao tác chính xác để truy xuất dữ liệu. SQL là khai báo — bạn mô tả kết quả mong muốn và hệ quản trị sẽ tìm cách đạt được. SQL dựa trên các khái niệm của đại số quan hệ nhưng cũng bao gồm các tính năng như tổng hợp, nhóm và sắp xếp mà đại số quan hệ không định nghĩa.
Toán tử chia trong đại số quan hệ là gì?
Division trả lời câu hỏi "những bộ nào trong quan hệ A có liên hệ với tất cả các bộ trong quan hệ B?" Nó được dùng khi bạn cần tìm các bản ghi khớp với mọi mục trong một quan hệ khác — như sinh viên đăng ký mọi học phần bắt buộc. Không có tương đương trực tiếp trong SQL; bạn mô phỏng bằng mẫu phủ định kép NOT EXISTS.
Sự khác nhau giữa natural join và equi join trong đại số quan hệ là gì?
Cả hai kiểu join đều ghép hàng bằng các điều kiện bằng nhau, nhưng cách xử lý cột trùng lặp khác nhau. Natural join tự động nối trên tất cả tên thuộc tính chung và loại bỏ các cột trùng khỏi kết quả. Equi join yêu cầu điều kiện tường minh và giữ cả hai bản sao của các cột nối trong đầu ra.
Mỗi khi bạn viết câu lệnh
SELECT, hệ quản trị cơ sở dữ liệu sẽ dịch nó thành một chuỗi thao tác hình thức. Quá trình dịch đó dựa trên đại số quan hệ — nền tảng toán học xác định cách dữ liệu được truy vấn và thao tác. Đây là thứ mà các hệ quản trị dùng để tối ưu truy vấn của bạn, và cũng là thứ nhà tuyển dụng hỏi đến khi họ muốn biết bạn hiểu cơ sở dữ liệu vượt ra ngoài những điều cơ bản.Đại số quan hệ mang đến cho bạn một mô hình tư duy về cách truy vấn hoạt động ở tầng sâu hơn. Khi đã hiểu nó, SQL sẽ trở nên hợp lý về mặt logic và bạn sẽ bắt đầu viết các truy vấn tối ưu hơn.
Trong bài viết này, tôi sẽ dẫn bạn qua các khái niệm cốt lõi, các toán tử nền tảng, các phép nối, và cách đại số quan hệ ánh xạ sang SQL mà bạn viết hằng ngày.