UNION ALL
UNION
当然可以,以下是几个通俗易懂的 UNION ALL 示例,结合实际使用场景,帮助你理解:
假设有两个表:
CREATE TABLE fruits1 (name VARCHAR(20)); CREATE TABLE fruits2 (name VARCHAR(20)); INSERT INTO fruits1 VALUES ('apple'), ('banana'); INSERT INTO fruits2 VALUES ('banana'), ('cherry');
SELECT name FROM fruits1 UNION ALL SELECT name FROM fruits2;
🔽 结果:
apple banana banana -- ✅ 没有去重 cherry
SELECT name FROM fruits1 UNION SELECT name FROM fruits2;
apple banana -- ⚠️ 重复项被去掉 cherry
CREATE TABLE employees ( id INT, name VARCHAR(50), manager_id INT ); INSERT INTO employees VALUES (1, 'Alice', NULL), -- CEO (2, 'Bob', 1), (3, 'Charlie', 2), (4, 'David', 2), (5, 'Eva', 3);
WITH RECURSIVE hierarchy AS ( SELECT id, name, manager_id FROM employees WHERE name = 'Alice' UNION ALL SELECT e.id, e.name, e.manager_id FROM employees e JOIN hierarchy h ON e.manager_id = h.id ) SELECT * FROM hierarchy;
id | name | manager_id ---|---------|------------ 1 | Alice | NULL 2 | Bob | 1 3 | Charlie | 2 4 | David | 2 5 | Eva | 3
✅ UNION ALL 是必须的,否则递归层级会被“去重”提前终止。
CTE(Common Table Expression,公共表表达式)是 SQL 中的一种临时结果集,它可以在一个查询的开头定义,并在后续的查询中像一个虚拟表一样使用,主要用于提高 SQL 可读性、结构化复杂逻辑,支持递归查询。
WITH cte_name AS ( SELECT ... FROM ... WHERE ... ) SELECT * FROM cte_name WHERE ...;
cte_name
CREATE TEMP TABLE
不使用 CTE:
SELECT name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);
使用 CTE:
WITH avg_salary AS ( SELECT AVG(salary) AS avg_sal FROM employees ) SELECT name, salary FROM employees, avg_salary WHERE salary > avg_salary.avg_sal;
✅ 可读性更好,逻辑更清晰。
id | name | manager_id ---|---------|------------ 1 | Alice | NULL 2 | Bob | 1 3 | Carol | 2 4 | Dave | 3
查找某个员工(如 Alice)下所有下属:
WITH RECURSIVE subordinates AS ( SELECT id, name, manager_id FROM employees WHERE name = 'Alice' UNION ALL SELECT e.id, e.name, e.manager_id FROM employees e JOIN subordinates s ON e.manager_id = s.id ) SELECT * FROM subordinates;
🔽 输出:
1 | Alice | NULL 2 | Bob | 1 3 | Carol | 2 4 | Dave | 3
✅ 递归 CTE 的关键:使用 UNION ALL,并引用自己。
WITH