CTE是SQL标准的特性之一,其本质是临时命名的结果集. CTE最初于1999年出现在SQL标准中,而第一个实现则于2007年开始出现。
CTE主要包括两种方式:
关键字with
作为CTE的标志,通过给定一个临时的名称,后面再跟上一个查询结果集,如下:
CTE和派生表(子查询)有些类似,例如:
使用CTE的SQL查询语句:
WITH engineers AS
( SELECT * FROM employees
WHERE dept = 'Engineering' )
SELECT * FROM engineers
WHERE ...
使用子查询的方式:
SELECT * FROM
( SELECT * FROM employees
WHERE dept = 'Engineering' ) AS engineers
WHERE
...
非递归CTE事实上是一个本地查询的视图,有许多优点和警告,该语法比嵌套的from (select ...)
更具可读性,一个CTE可以引用另一个CTE,并且可以从多个地方引用它.
与嵌套的FROM (SELECT...)
子句相比,使用这种格式可使得SQL语句更具可读性,示例如下:
WITH engineers AS (
SELECT * FROM employees
WHERE dept IN('Development','Support') ),
eu_engineers AS ( SELECT * FROM engineers WHERE country IN('NL',...) )
SELECT
...
FROM eu_engineers;
一种自我join语句的方式,例如:
WITH engineers AS (
SELECT * FROM employees
WHERE dept IN('Development','Support') )
SELECT * FROM engineers E1
WHERE NOT EXISTS
(SELECT 1 FROM engineers E2
WHERE E2.country=E1.country
AND E2.name <> E1.name );
Or, for year-over-year comparisons, for example:
WITH sales_product_year AS (
SELECT product, YEAR(ship_date) AS year,
SUM(price) AS total_amt
FROM item_sales
GROUP BY product, year )
SELECT *
FROM sales_product_year CUR,
sales_product_year PREV,
WHERE CUR.product=PREV.product
AND CUR.year=PREV.year + 1
AND CUR.total_amt > PREV.total_amt
Another use is to compare individuals against their group. Below is an example of how this might be executed :
WITH sales_product_year AS (
SELECT product,
YEAR(ship_date) AS year,
SUM(price) AS total_amt
FROM item_sales
GROUP BY product, year
)
SELECT *
FROM sales_product_year S1
WHERE
total_amt >
(SELECT 0.1 * SUM(total_amt)
FROM sales_product_year S2
WHERE S2.year = S1.year)
递归的CTE表达式在
MariaDB 10.2.2
版本才提供支持
CTE允许查询引用自身.递归CTE将重复执行数据的子集,知道获得完整的结果期.
这对于处理分层或树状数据特别有用。 max_recursive_iterations参数避免了无限循环。
max_recursive_iterations
numeric
4294967295
0
to 4294967295
通过关键字with recursive
来标识此为一个递归CTE语句.通过临时指定一个别名,然后跟上一个查询结果集语句
给定一下数据表结构
首先执行查询,获取得到name='Alex’的记录
然后执行递归部分语句
从计算方式我们得到一个语法结构,如下:
with recursive R as (
select anchor_data
union [all]
select recursive_part
from R, ...
)
select ...
WITH关键字表示Common Table Expression(CTE)。它使您可以在查询中多次引用子查询表达式,就好像有一个仅在查询期间存在的临时表一样。
非递归CTE表达式在MariaDB 10.2.1开始支持
递归CTE表达式在MariaDB 10.2.2 开始支持
WITH [RECURSIVE] table_reference as (SELECT ...)
SELECT ...
您可以将table_reference用作外部SELECT部分中的任何普通表。您也可以在子查询中使用WITH。 WITH也可以与EXPLAIN和SELECT一起使用。
示例:
WITH t AS (SELECT a FROM t1 WHERE b >= 'c')
SELECT * FROM t2, t WHERE t2.c = t.a;
子查询
SELECT t1.a, t1.b FROM t1, t2
WHERE t1.a > t2.c
AND t2.c IN(WITH t AS (SELECT * FROM t1 WHERE t1.a < 5)
SELECT t2.c FROM t2, t WHERE t2.c = t.a);
递归CTE示例:
WITH RECURSIVE ancestors AS
( SELECT * FROM folks
WHERE name="Alex"
UNION
SELECT f.*
FROM folks AS f, ancestors AS a
WHERE f.id = a.father OR f.id = a.mother )
SELECT * FROM ancestors;
pid=0代表当前是顶级父节点
我们要查询资源域
下的所有子节点,SQL语句如下:
with recursive teg as (
select * from ds_category where id='38f15a7ff91e4739b72fe28fdbd2eeec'
union
select d.* from ds_category d ,teg as tg
where d.pid=tg.id
) select * from teg