MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)

CTE是SQL标准的特性之一,其本质是临时命名的结果集. CTE最初于1999年出现在SQL标准中,而第一个实现则于2007年开始出现。

CTE主要包括两种方式:

  • 非递归
  • 递归

非递归CTE

关键字with作为CTE的标志,通过给定一个临时的名称,后面再跟上一个查询结果集,如下:
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第1张图片
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,并且可以从多个地方引用它.

引用另外一个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;

CTE的多种用途

一种自我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

递归的CTE表达式在MariaDB 10.2.2版本才提供支持

SQL通常在递归结构方面表现很差.
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第2张图片

CTE允许查询引用自身.递归CTE将重复执行数据的子集,知道获得完整的结果期.

这对于处理分层或树状数据特别有用。 max_recursive_iterations参数避免了无限循环。

max_recursive_iterations

  • 描述:递归执行的最大次数
  • 命令行: --max-recursive-iterations=#
  • Scope:Global、Session
  • Dynamic: Yes
  • 数据类型: numeric
  • 默认值: 4294967295
  • 范围: 0 to 4294967295
  • 介绍: MariaDB 10.2.2

递归语法

通过关键字with recursive来标识此为一个递归CTE语句.通过临时指定一个别名,然后跟上一个查询结果集语句
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第3张图片

计算方式

给定一下数据表结构

MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第4张图片

首先执行查询,获取得到name='Alex’的记录

MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第5张图片

然后执行递归部分语句

MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第6张图片
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第7张图片
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第8张图片
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第9张图片
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第10张图片

总结

从计算方式我们得到一个语法结构,如下:

with recursive R as (
  select anchor_data
  union [all]
  select recursive_part
  from R, ...
)
select ...

With语法

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;

示例

例如我们存在如下数据结构
MariaDB常用表达式(递归与非递归)-CTE(Common Table Expressions)_第11张图片

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 

你可能感兴趣的:(程序杂记,MariaDB,CTE,Common,Table,Expressions,SQL递归,递归)