关系代数详解与SQL示例
关系代数是关系数据库的理论基础,它提供了一组操作符用于操作关系(表)
1. 基本操作
1.1 选择 (Selection, σ)
选择操作从关系中选择满足特定条件的元组(行)。
关系代数表示:σ条件(R)
SQL示例:
-- 选择年龄大于30的员工
SELECT * FROM Employees WHERE age > 30;
1.2 投影 (Projection, π)
投影操作从关系中选择特定的属性(列)。
关系代数表示:π属性列表(R)
SQL示例:
-- 选择员工的姓名和部门
SELECT name, department FROM Employees;
1.3 并集 (Union, ∪)
并集操作合并两个相容关系(相同属性)的所有元组,去除重复。
关系代数表示:R ∪ S
SQL示例:
-- 合并两个部门的员工列表
SELECT * FROM Dept1_Employees
UNION
SELECT * FROM Dept2_Employees;
1.4 差集 (Set Difference, -)
差集操作返回在第一个关系但不在第二个关系中的元组。
关系代数表示:R - S
SQL示例:
-- 找出在Dept1但不在Dept2的员工
SELECT * FROM Dept1_Employees
EXCEPT
SELECT * FROM Dept2_Employees;
1.5 笛卡尔积 (Cartesian Product, ×)
笛卡尔积操作返回两个关系的所有可能组合。
关系代数表示:R × S
SQL示例:
-- 员工和部门的笛卡尔积
SELECT * FROM Employees, Departments;
1.6 重命名 (Rename, ρ)
重命名操作改变关系的名称或属性名称。
关系代数表示:ρ新名称(R)
SQL示例:
-- 重命名表和列
SELECT emp_id AS employee_id, name AS employee_name FROM Employees AS Emp;
2. 派生操作
2.1 连接 (Join, ⋈)
连接操作是选择+笛卡尔积的组合,根据条件连接两个关系。
关系代数表示:R ⋈条件 S
SQL示例:
-- 内连接:员工和他们的部门信息
SELECT * FROM Employees E JOIN Departments D ON E.dept_id = D.dept_id;-- 自然连接(自动匹配同名属性)
-- 注意:SQL没有直接的自然连接语法,但可以模拟
SELECT E.*, D.department_name
FROM Employees E JOIN Departments D USING (dept_id);
2.2 交 (Intersection, ∩)
交操作返回同时在两个关系中的元组。
关系代数表示:R ∩ S
SQL示例:
-- 找出同时在两个部门的员工
SELECT * FROM Dept1_Employees
INTERSECT
SELECT * FROM Dept2_Employees;
2.3 除法 (Division, ÷)
除法操作返回满足特定条件的元组,常用于"全部"类查询。
关系代数表示:R ÷ S
SQL示例:
-- 找出选修了所有必修课的学生
-- 关系代数: π_student_id,course_id(Enrollment) ÷ π_course_id(RequiredCourses)
SELECT DISTINCT student_id
FROM Enrollment E1
WHERE NOT EXISTS (SELECT course_id FROM RequiredCoursesEXCEPTSELECT course_id FROM Enrollment E2 WHERE E2.student_id = E1.student_id
);
3. 高级操作
3.1 θ-连接 (Theta Join)
基于任意条件的连接操作。
SQL示例:
-- 找出工资高于经理的员工
SELECT E1.*
FROM Employees E1 JOIN Employees E2
ON E1.manager_id = E2.emp_id AND E1.salary > E2.salary;
3.2 半连接 (Semi Join)
只返回左关系中能与右关系连接的元组。
SQL示例:
-- 找出有下属的经理
SELECT DISTINCT M.*
FROM Employees M
WHERE EXISTS (SELECT 1 FROM Employees E WHERE E.manager_id = M.emp_id
);
3.3 反连接 (Anti Join)
返回左关系中不能与右关系连接的元组。
SQL示例:
-- 找出没有下属的员工
SELECT E.*
FROM Employees E
WHERE NOT EXISTS (SELECT 1 FROM Employees M WHERE M.manager_id = E.emp_id
);
4. 聚合操作
关系代数扩展包括聚合函数。
SQL示例:
-- 计算每个部门的平均工资
SELECT department, AVG(salary)
FROM Employees
GROUP BY department;-- 关系代数表示: γ<department; AVG(salary)>(Employees)
5. 综合示例
查询:找出工资高于部门平均工资的员工
-- 使用关系代数可以表示为:
-- π_E.* (σ_E.salary > avg_salary (E ⋈ dept_id=dept_id γ_dept_id; AVG(salary)→avg_salary(E)))-- SQL实现:
SELECT E.*
FROM Employees E
JOIN (SELECT dept_id, AVG(salary) AS avg_salaryFROM EmployeesGROUP BY dept_id
) D ON E.dept_id = D.dept_id
WHERE E.salary > D.avg_salary;
关系代数为SQL提供了理论基础,理解关系代数有助于编写更高效、更准确的SQL查询。