通用表表达式(Common Table Expression)能够简化复杂的子查询和连接查询,实现树状结构数据的遍历,提高 SQL 语句的可读性和性能。
sqlWITH cte_name(col1, col2, ...) AS (
subquery
)
SELECT * FROM cte_name;
sqlWITH t(n) AS (
SELECT 1 -- oracle 需要使用 SELECT 1 FROM dual
)
SELECT n
FROM t;
WITH 语句定义了一个变量,这个变量的值是一个表,所以称为通用表表达式。CTE 和临时表或子查询类似,可以用于 SELECT、INSERT、UPDATE 以及 DELETE 等语句。
sql-- 定义多个 CTE
WITH t1(n) AS (
SELECT 1 -- oracle 需要使用 SELECT 1 FROM dual
),
t2(m) AS (
SELECT n+1
FROM t1 -- 可以引用前面的 CTE
)
SELECT t1.n, t2.m
FROM t1
CROSS JOIN t2;
sqlWITH RECURSIVE cte_name AS (
cte_query_initial -- 初始化部分
UNION [ALL] -- 合并
cte_query_iterative -- 递归部分,可以对当前 CTE 进行自我引用
) SELECT * FROM cte_name;
一些使用示例。
sql-- 递归生成1~10
-- mysql pg sqlite
WITH RECURSIVE t(n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM t WHERE n < 10
)
SELECT n FROM t;
-- oracle
WITH t(n) AS
(
SELECT 1 FROM dual
UNION ALL
SELECT n + 1 FROM t WHERE n < 10
)
SELECT n FROM t;
-- mss
WITH t(n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM t WHERE n < 10
)
SELECT n FROM t;
sql-- 遍历层次/树结构,自顶向下
-- mysql
WITH RECURSIVE employee_path (emp_id, emp_name, path) AS
(
-- 初始部分
SELECT emp_id, emp_name, emp_name AS path
FROM employee
WHERE manager IS NULL -- 老板,是树的根
UNION ALL
-- 递归部分
SELECT e.emp_id, e.emp_name, CONCAT(ep.path, '->', e.emp_name)
FROM employee_path ep
JOIN employee e ON ep.emp_id = e.manager -- 当前层关联下一层
)
SELECT emp_name AS "员工姓名", path AS "管理路径"
FROM employee_path
ORDER BY emp_id;
本文作者:jdxj
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!