MariaDB CTE公用表达式
公用表达式(Common Table Expressions,简称CTE)
Maria DB 版本为10.2.2以上的才支持 WITH 语法
CTE 介绍
WITH关键字表示公用表表达式(CTE)
它使您可以在查询中多次引用子查询表达式,就好像有一个仅在查询期间存在的临时表一样。
语法(Syntax)
WITH [RECURSIVE] table_reference as (SELECT ...)
SELECT ...
您可以将table_reference用作外部SELECT部分中的任何普通表。您也可以在子查询中使用WITH。WITH也可以与EXPLAIN和SELECT一起使用。
以下是在顶级使用WITH的示例:
WITH t AS (SELECT a FROM t1 WHERE b >= 'c')
SELECT * FROM t2, t WHERE t2.c = t.a;
下面的示例在子查询中使用WITH:
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;
公用表表达式(CTE)是标准的SQL功能,本质上是临时命名的结果集
CTE有两种类别:
- 非递归CTE
- 递归CTE
非递归CTE
WITH关键字表示CTE,它具有一个名称,后跟一个正文(主要查询的语句),如下所示
CTE与派生表相似。例如:
WITH engineers AS
( SELECT * FROM employees
WHERE dept = 'Engineering' )
SELECT * FROM engineers
WHERE ...
顶级使用CTE
SELECT * FROM
( SELECT * FROM employees
WHERE dept = 'Engineering' ) AS engineers
WHERE ...
子查询中使用CTE
基本上,非递归CTE是本地查询的VIEW。有许多优点和警告。该语法比嵌套的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的多种用途
这可以是“anti-self 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 );
或者,对于逐年比较,例如:
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
另一个用途是将个人与他们的团体进行比较。以下是如何执行此操作的示例:
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)是标准的SQL功能,本质上是临时命名的结果集。CTE最初于1999年出现在SQL标准中,而第一个实现则于2007年开始出现。
SQL通常在递归结构方面很差。
CTE允许查询引用自身。递归CTE将重复执行数据的子集,直到获得完整的结果集。这对于处理分层或树状数据特别有用。max_recursive_iterations 避免了无限循环。
语法示例
WITH RECURSIVE 表示递归CTE,它具有一个名称,后跟一个正文(主要查询),如下所示:
计算方式(Computation)
给出以下结构:
首先执行查询的锚点部分:
接下来,执行查询的递归部分:
Summary so far(到目前为止的总结)
with recursive R as (
select anchor_data
union [all]
select recursive_part
from R, ...
)
select ...
- 计算anchor_data
- 计算recursive_part以获取新数据
- 如果(新数据为非空)转到2;
CAST避免截断数据
正如MariaDB和SQL标准当前实现的那样,如果数据转换不正确,数据可能会被截断。如果CTE的递归部分为列生成的值比CTE的非递归部分宽,则必须将列CAST正确的宽度。
Examples
传递闭包-确定总线目的地
样本数据:
CREATE TABLE bus_routes (origin varchar(50), dst varchar(50));
INSERT INTO bus_routes VALUES
('New York', 'Boston'),
('Boston', 'New York'),
('New York', 'Washington'),
('Washington', 'Boston'),
('Washington', 'Raleigh');
现在,我们要返回以纽约(New York)为起点的巴士目的地:
WITH RECURSIVE bus_dst as (
SELECT origin as dst FROM bus_routes WHERE origin='New York'
UNION
SELECT bus_routes.dst FROM bus_routes, bus_dst WHERE bus_dst.dst= bus_routes.origin
)
SELECT * FROM bus_dst;
+------------+
| dst |
+------------+
| New York |
| Boston |
| Washington |
| Raleigh |
+------------+
上面的示例计算如下:
首先,计算anchor 数据:
- 从纽约(New York)出发
- 添加了波士顿(Boston)和华盛顿(Washington)
接下来,递归部分:
- 从波士顿(Boston)出发,然后从华盛顿(Washington)出发
- 罗利(Raleigh)被添加
- UNION排除已经存在的节点。
计算路径-确定总线(Bus)路线
这次,我们尝试获取诸如“纽约->华盛顿->罗利”之类的巴士路线。
New York -> Washington -> Raleigh
使用与上一个示例相同的样本数据:
WITH RECURSIVE paths (cur_path, cur_dest) AS (
SELECT origin, origin FROM bus_routes WHERE origin='New York'
UNION
SELECT CONCAT(paths.cur_path, ',', bus_routes.dst), bus_routes.dst
FROM paths, bus_routes
WHERE paths.cur_dest = bus_routes.origin AND
NOT FIND_IN_SET(bus_routes.dst, paths.cur_path)
)
SELECT * FROM paths;
+-----------------------------+------------+
| cur_path | cur_dest |
+-----------------------------+------------+
| New York | New York |
| New York,Boston | Boston |
| New York,Washington | Washington |
| New York,Washington,Boston | Boston |
| New York,Washington,Raleigh | Raleigh |
+-----------------------------+------------+
CAST避免数据被截断
在下面的示例中,数据被截断,因为结果没有明确地转换为足够宽的类型:
WITH RECURSIVE tbl AS (
SELECT NULL AS col
UNION
SELECT "THIS NEVER SHOWS UP" AS col FROM tbl
)
+------+
| col |
+------+
| NULL |
| |
+------+
明确使用CAST来克服此问题:
WITH RECURSIVE tbl AS (
SELECT CAST(NULL AS CHAR(50)) AS col
UNION SELECT "THIS NEVER SHOWS UP" AS col FROM tbl
)
SELECT * FROM tbl;
+---------------------+
| col |
+---------------------+
| NULL |
| THIS NEVER SHOWS UP |
+---------------------+
MariaDB CTE公用表达式的更多相关文章
- sql server数据库性能优化之2-避免使用CTE公用表达式的递归【by zhang502219048】
数据库优化中的一个实例,记录一下: 1. 原来用了CTE公用表达式的递归,reads高达约40万,看查询执行计划,使用了Nested Loops: 2. 优化去掉递归,改用其它方式实现,reads降低 ...
- 【转】CTE(公用表表达式)
本文转自:爽朗的微笑 http://www.cnblogs.com/shuangnet/archive/2013/03/22/2975929.html 公用表表达式 (CTE) 具有一个重要的优点, ...
- 关于使用CTE(公用表表达式)的递归查询
--关于使用CTE(公用表表达式)的递归查询 --CTE 的基本语法结构如下: WITH expression_name [ ( column_name [,...n] ) ] AS ( CTE_qu ...
- Sql Server 公用表达式(CTE)
简介 对于select查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可续,在一个查询中引入另外的结果集都是通过视图而不是子查询来进行分解的,但是,视图是作为系统对象存在数据库中,那对于结果集 ...
- SqlServer:SqlServer(sql,游标,定时作业,行转列,列转行,公用表达式递归,merge合并)
1.加载驱动: Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); DriverManager.getCo ...
- Sql — CTE公用表表达式和With用法总结
CTE(Common Table Expression) 公用表表达式,它是在单个语句的执行范围内定义的临时结果集,只在查询期间有效.它可以自引用,也可在同一查询中多次引用,实现了代码段的重复利用. ...
- sql中with的用法(CTE公用表表达式):应用子查询嵌套,提高sql性能
一.WITH AS的含义 WITH AS短语,也叫子查询部分(subquery factoring),定义一个SQL片断,该片断会被整个SQL语句所用到. 有时是为了让SQL语句的可读性更高些,也可能 ...
- 使用CTE公用表表达式的递归查询(WITH AS)
公用表表达式 (CTE) 具有一个重要的优点,那就是能够引用其自身,从而创建递归 CTE.递归 CTE 是一个重复执行初始 CTE 以返回数据子集直到获取完整结果集的公用表表达式. 当某个查询引用递归 ...
- CTE(公用表表达式)
-> 将复杂的派生表写在中间from子句中变得十分臃肿,给为维护等操作带来麻烦 -> 将这个派生表要是能提前到前面,给一个别名,后面查询的时候直接使用别名即可语法: with 表的别名 a ...
随机推荐
- BI驾驶舱是什么?BI管理驾驶舱主要内容及特点
BI驾驶舱,顾名思义就是商业智能中让企业管理者对企业的管理能够找到在飞机或汽车驾驶舱里面的驾驶感觉.BI管理驾驶舱系统是专为企业管理层设计的BI分析系统,,是为企业高层打造的虚拟办公场景,有利于更好地 ...
- java策略模式拙见
面向对象的两个基本准则: 单一职责:一个类只有一个发生变化的原因 开闭原则:对拓展开放,对修改关闭 <Java开发手册>中,有这样的规则:超过3层的 if-else 的逻辑判断代码可以使用 ...
- C语言中sizeof()的用法
语法 sizeof有三种语法形式: 1.sizeof(object); //sizeof(对象); 2.sizeof(type_name); //sizeof(类型); 3.sizeof object ...
- Oracle之表和字段的注释
给表名加上注释 --给表名加上注释的语法结构 --语法结构:COMMENT ON TABLE 英文表名 IS '中文注释' COMMENT ON TABLE DEPT IS '部门表'; 给字段加上注 ...
- 在linux上oracle服务启动停止详细
转至:https://www.cnblogs.com/baihuitestsoftware/articles/6365431.html 在CentOS 6.3下安装完Oracle 10g R2,重开机 ...
- WPS二级标题链接到一级标题
WPS二级标题链接到一级标题,即2后出现2.1 2.2而不是1.3 1.4什么的 样式中的编号什么的都不用动,默认即可,关键在于这些多级标题是否选择了同一个编号方式 WPS中,只需要将它们的编号选择为 ...
- 革命性创新,动画杀手锏 @scroll-timeline
在 CSS 规范 Scroll-linked Animations 中,推出了一个划时代的 CSS 功能.也就是 -- The @scroll-timeline at-rule,直译过来就是滚动时间线 ...
- 基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中
在我的各种开发框架中,数据访问有的基于微软企业库,有的基于EFCore的实体框架,两者各有其应用场景,不过多的去比较.最近在使用SqlSugar的时候,觉得这个数据访问处理的组件确实很灵活,据说性能也 ...
- laravel7 数据库数据导出至 xlsx
网址参考: https://learnku.com/articles/32391 1:安装excel插件 安装方式 composer require maatwebsite/excel 2:excel ...
- tp 5 三级联动查询(自写)
思路: 1.定义路由 2.查询顶级分类(pid=0)发送至制图 3.循环展示 4.给顶级分类下拉框绑定内容改变事件(JS:onchange.JQ:change) 5.获取到选中的option的valu ...