当前位置: 首页 > news >正文

mysql with 的用法 (含 with recursive)

mysql with 的用法 (含 with recursive)

相关基础

AS 用法

as 在 mysql 中用来给列/表起别名
如:

-- 给列起别名, 把列为name的别名命名为student_name
select name as student_name from student;
-- 给表起别名, 把表student的别名命名为data_list
select * from student as data_list;
-- 给查询结果/表达式起别名
select length(name) as name_length from student;

UNION 用法

union 用于结合多个 sql 查询结果于单个结果集中

query_expression_body UNION [ALL | DISTINCT] query_block[UNION [ALL | DISTINCT] query_expression_body][...]
mysql> SELECT 1, 2;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+mysql> SELECT 'a', 'b';
+---+---+
| a | b |
+---+---+
| a | b |
+---+---+mysql> SELECT 1, 2 UNION SELECT 'a', 'b';
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
| a | b |
+---+---+

with (Common Table Expressions)

Common Table Expressions(CTE)是一个命名的临时结果集,存在于单个语句的范围内,以后该临时结果集可以在该语句中引用, 甚至可能多次引用。
语法:

with_clause:WITH [RECURSIVE]cte_name [(col_name [, col_name] ...)] AS (subquery)[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

示例:

WITHcte1 AS (SELECT a, b FROM table1),cte2 AS (SELECT c, d FROM table2)
SELECT b, d FROM cte1 JOIN cte2
WHERE cte1.a = cte2.c;
--下面两个查询等价
WITH cte (col1, col2) AS
(SELECT 1, 2UNION ALLSELECT 3, 4
)
SELECT col1, col2 FROM cte;WITH cte AS
(SELECT 1 AS col1, 2 AS col2UNION ALLSELECT 3, 4
)
SELECT col1, col2 FROM cte;

用法

  1. 在 select, update, delete 语句前

    WITH ... SELECT ...
    WITH ... UPDATE ...
    WITH ... DELETE ...
    
  2. 在子查询前

    SELECT ... WHERE id IN (WITH ... SELECT ...) ...
    SELECT * FROM (WITH ... SELECT ...) AS dt ...
    
  3. 于含 select 的语句的 select 前

    INSERT ... WITH ... SELECT ...
    REPLACE ... WITH ... SELECT ...
    CREATE TABLE ... WITH ... SELECT ...
    CREATE VIEW ... WITH ... SELECT ...
    DECLARE CURSOR ... WITH ... SELECT ...
    EXPLAIN ... WITH ... SELECT ...
    
  4. 同一级别只允许一个 WITH 子句

    -- 错误示范
    WITH cte1 AS (...) WITH cte2 AS (...) SELECT ...
    -- 正确示范1
    WITH cte1 AS (...), cte2 AS (...) SELECT ...
    -- 正确示范2, 语句中可含有多个with, 前提是他们都在不同的层级
    WITH cte1 AS (SELECT 1)SELECT * FROM (WITH cte2 AS (SELECT 2) SELECT * FROM cte2 JOIN cte1) AS dt;
    
  5. 一个 with 语句能定义一个或多个 CTE, 但每个 CTE 在该语句中都是唯一的

    -- 错误示范, 两个cte命名都是cte1
    WITH cte1 AS (...), cte1 AS (...) SELECT ...
    -- 正确示范
    WITH cte1 AS (...), cte2 AS (...) SELECT ...
    

递归 CTE (Recursive Common Table Expressions)

示例 1 递归增长

WITH RECURSIVE cte (n) AS
(SELECT 1UNION ALLSELECT n + 1 FROM cte WHERE n < 5
)
SELECT * FROM cte;

上述 sql 输出结果如下:

+------+
| n    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+

该 sql 可以分成两部分, 一部分是非递归部分, 用于初始化行数据:

SELECT 1

另一部分是递归部分:

SELECT n + 1 FROM cte WHERE n < 5

等价于以下代码:

(function test(a) {console.log(a);a++;if (a <= 5) {test(a);}
})(1);// 1
// 2
// 3
// 4
// 5

示例 2 递归字符串拼接

WITH RECURSIVE cte AS
(SELECT 1 AS n, 'abc' AS strUNION ALLSELECT n + 1, CONCAT(str, str) FROM cte WHERE n < 3
)
SELECT * FROM cte;

非严格模式下, 输出以下内容:

+------+------+
| n    | str  |
+------+------+
|    1 | abc  |
|    2 | abc  |
|    3 | abc  |
+------+------+

严格模式下, 则会报错: ERROR 1406 (22001): Data too long for column 'str' at row 1

定义str列时, 用abc定义, 该操作同时定义了长度为length(abc), 故拼接时, 会超出长度
将上述 sql 调整一下

WITH RECURSIVE cte AS
(SELECT 1 AS n, CAST('abc' AS CHAR(20)) AS strUNION ALLSELECT n + 1, CONCAT(str, str) FROM cte WHERE n < 3
)
SELECT * FROM cte;

即可正常输出:

+------+--------------+
| n    | str          |
+------+--------------+
|    1 | abc          |
|    2 | abcabc       |
|    3 | abcabcabcabc |
+------+--------------+

限制 CTE 循环次数

输入以下 sql 时, 会提示Recursive query aborted after 1048577 iterations. Try increasing @@cte_max_recursion_depth to a larger value.

WITH RECURSIVE cte (n) AS
(SELECT 1UNION ALLSELECT n + 1 FROM cte
)
SELECT * FROM cte;

默认情况下, cte_max_recursion_depth的值为 1000, 会限制 CTE 的循环次数, 可以通过修改cte_max_recursion_depth修改循环次数上限.

通过修改cte_max_recursion_depth修改循环次数上限后, 可通过limit限制上限.

cte_max_recursion_depth>=limit
故当 limit 较大时, 需先修改cte_max_recursion_depth, 否则较大的limit不生效

WITH RECURSIVE cte (n) AS
(SELECT 1UNION ALLSELECT n + 1 FROM cte LIMIT 10000
)
SELECT * FROM cte;

斐波那契数列

WITH RECURSIVE fibonacci (n, fib_n, next_fib_n) AS
(SELECT 1, 0, 1UNION ALLSELECT n + 1, next_fib_n, fib_n + next_fib_nFROM fibonacci WHERE n < 10
)
SELECT * FROM fibonacci;
+------+-------+------------+
| n    | fib_n | next_fib_n |
+------+-------+------------+
|    1 |     0 |          1 |
|    2 |     1 |          1 |
|    3 |     1 |          2 |
|    4 |     2 |          3 |
|    5 |     3 |          5 |
|    6 |     5 |          8 |
|    7 |     8 |         13 |
|    8 |    13 |         21 |
|    9 |    21 |         34 |
|   10 |    34 |         55 |
+------+-------+------------+

日期序列生成

mysql> SELECT * FROM sales ORDER BY date, price;
+------------+--------+
| date       | price  |
+------------+--------+
| 2022-01-03 | 100.00 |
| 2022-01-03 | 200.00 |
| 2022-01-06 |  50.00 |
| 2022-01-08 |  10.00 |
| 2022-01-08 |  20.00 |
| 2022-01-08 | 150.00 |
| 2022-01-17 |   5.00 |
+------------+--------+

求每日总sales

mysql> SELECT date, SUM(price) AS sum_priceFROM salesGROUP BY dateORDER BY date;
+------------+-----------+
| date       | sum_price |
+------------+-----------+
| 2022-01-10 |    300.00 |
| 2022-01-13 |     50.00 |
| 2022-01-15 |    180.00 |
| 2022-01-17 |      5.00 |
+------------+-----------+

这样产生的结果, 中间会缺少部分日期.
先写个 sql, 根据日期, 输出中间的日期列表:

WITH RECURSIVE dates (date) AS
(SELECT MIN(date) FROM salesUNION ALLSELECT date + INTERVAL 1 DAY FROM datesWHERE date + INTERVAL 1 DAY <= (SELECT MAX(date) FROM sales)
)
SELECT * FROM dates;
+------------+
| date       |
+------------+
| 2022-01-10 |
| 2022-01-11 |
| 2022-01-12 |
| 2022-01-13 |
| 2022-01-14 |
| 2022-01-15 |
| 2022-01-16 |
| 2022-01-17 |
+------------+

结合上述 sql:

WITH RECURSIVE dates (date) AS
(SELECT MIN(date) FROM salesUNION ALLSELECT date + INTERVAL 1 DAY FROM datesWHERE date + INTERVAL 1 DAY <= (SELECT MAX(date) FROM sales)
)
SELECT dates.date, COALESCE(SUM(price), 0) AS sum_price
FROM dates LEFT JOIN sales ON dates.date = sales.date
GROUP BY dates.date
ORDER BY dates.date;
+------------+-----------+
| date       | sum_price |
+------------+-----------+
| 2022-01-10 |    300.00 |
| 2022-01-11 |      0.00 |
| 2022-01-12 |      0.00 |
| 2022-01-13 |     50.00 |
| 2022-01-14 |      0.00 |
| 2022-01-15 |    180.00 |
| 2022-01-16 |      0.00 |
| 2022-01-17 |      5.00 |
+------------+-----------+

分层数据遍历

简单写个 sql, 建表并插入数据

CREATE TABLE employees (id         INT PRIMARY KEY NOT NULL,name       VARCHAR(100) NOT NULL,manager_id INT NULL,INDEX (manager_id),
FOREIGN KEY (manager_id) REFERENCES employees (id)
);
INSERT INTO employees VALUES
(117, "Zzs", NULL),      # zzs is the boss (manager_id is NULL)
(198, "John", 117),      # John has ID 198 and reports to 117 (zzs)
(692, "Tarek", 117),
(29, "Pedro", 198),
(4610, "Sarah", 29),
(72, "Pierre", 29),
(123, "Adil", 692);

此时数据库内数据如下:

mysql> SELECT * FROM employees ORDER BY id;
+------+---------+------------+
| id   | name    | manager_id |
+------+---------+------------+
|   29 | Pedro   |        198 |
|   72 | Pierre  |         29 |
|  117 | Zzs     |       NULL |
|  123 | Adil    |        692 |
|  198 | John    |        117 |
|  692 | Tarek   |        117 |
| 4610 | Sarah   |         29 |
+------+---------+------------+

通过以下 sql, 查询出管理链路:

WITH RECURSIVE employee_paths (id, name, path) AS
(SELECT id, name, CAST(id AS CHAR(200))FROM employeesWHERE manager_id IS NULLUNION ALLSELECT e.id, e.name, CONCAT(ep.path, ',', e.id)FROM employee_paths AS ep JOIN employees AS eON ep.id = e.manager_id
)
SELECT * FROM employee_paths ORDER BY path;

查询结果如下:

+------+---------+-----------------+
| id   | name    | path            |
+------+---------+-----------------+
|  117 | Zzs     | 117             |
|  198 | John    | 117,198         |
|   29 | Pedro   | 117,198,29      |
| 4610 | Sarah   | 117,198,29,4610 |
|   72 | Pierre  | 117,198,29,72   |
|  692 | Tarek   | 117,692         |
|  123 | Adil    | 117,692,123     |
+------+---------+-----------------+

参考文档

WITH (Common Table Expressions)

相关文章:

mysql with 的用法 (含 with recursive)

mysql with 的用法 (含 with recursive) 相关基础 AS 用法 as 在 mysql 中用来给列/表起别名 如: -- 给列起别名, 把列为name的别名命名为student_name select name as student_name from student; -- 给表起别名, 把表student的别名命名为data_list select * from student…...

YOLOv8模型ONNX格式INT8量化轻松搞定

ONNX格式模型量化 深度学习模型量化支持深度学习模型部署框架支持的一种轻量化模型与加速模型推理的一种常用手段&#xff0c;ONNXRUNTIME支持模型的简化、量化等脚本操作&#xff0c;简单易学&#xff0c;非常实用。 ONNX 模型量化常见的量化方法有三种&#xff1a;动态量化…...

揭秘南卡开放式耳机创新黑科技,核心技术剑指用户痛点

随着科技的进步和人们娱乐方式的升级&#xff0c;大家对听音工具的选择&#xff0c;从传统的耳机到蓝牙耳机再到AirPods这样的真无线耳机&#xff0c;而今年&#xff0c;也有一种全新的耳机爆发式涌入人们之中&#xff0c;那就是开放式耳机。 开放式耳机的出现&#xff0c;满足…...

ChatRule:基于知识图推理的大语言模型逻辑规则挖掘11.10

ChatRule&#xff1a;基于知识图推理的大语言模型逻辑规则挖掘 摘要引言相关工作初始化和问题定义方法实验 摘要 逻辑规则对于揭示关系之间的逻辑联系至关重要&#xff0c;这可以提高推理性能并在知识图谱&#xff08;KG&#xff09;上提供可解释的结果。虽然已经有许多努力&a…...

6.4翻转二叉树(LC226—送分题,前序遍历)

算法&#xff1a; 第一想法是用昨天的层序遍历&#xff0c;把每一层level用切片反转。但是这样时间复杂度很高。 其实只要在遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。 这道题目使用前序遍历和后序遍历都可以&#xff0c;唯独中序遍历不方便&#x…...

【斗罗二】霍雨浩拿下满分碾压戴华斌,动用家族力量,海神阁会议

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 深度爆料《绝世唐门》第23话最新预告分析&#xff0c;魂兽升学考试中一场白虎魂师戴华斌与千年级别的风虎的决斗即将上演。风虎&#xff0c;作为虎类魂兽的王者&#xff0c;其强大的实力和独特的技能让这场战…...

通义千问, 文心一言, ChatGLM, GPT-4, Llama2, DevOps 能力评测

引言 “克隆 dev 环境到 test 环境&#xff0c;等所有服务运行正常之后&#xff0c;把访问地址告诉我”&#xff0c;“检查所有项目&#xff0c;告诉我有哪些服务不正常&#xff0c;给出异常原因和修复建议”&#xff0c;在过去的工程师生涯中&#xff0c;也曾幻想过能够通过这…...

一键创建PDF文档,高效管理您的文件资料

在繁忙的工作中&#xff0c;您是否曾为处理PDF文件而感到烦恼&#xff1f;现在&#xff0c;我们为您推荐一款全新的高效PDF文档管理工具——一键创建PDF文档&#xff0c;让您的工作效率瞬间提升&#xff01; 首先&#xff0c;在首助编辑高手的主页面板块栏里&#xff0c;选择“…...

React在 JSX 中进行条件渲染和循环,并使用条件语句和数组的方法(如 map)来动态生成组件或元素

在 JSX 中进行条件渲染和循环&#xff0c;你可以使用条件语句&#xff08;如 if-else&#xff09;和数组的方法&#xff08;如 map&#xff09;来动态生成组件或元素。以下是一些示例来说明这些概念&#xff1a; 条件渲染&#xff1a; import React from react;const MyCompo…...

数据结构-二叉树的遍历及相关应用

1、定义二叉树结点结构 2、编写主程序 3、三种方法遍历二叉树&#xff0c;并实现求树的深度&#xff0c;叶子数&#xff0c;某一层的结点数 4、实现代码&#xff08;带交互界面&#xff09; #include<iostream> using namespace std; typedef struct BiTNode {char d…...

机器人入门(五)—— 仿真环境中操作TurtleBot

仿真环境中操作TurtleBot 一、实操1.1 查看姿态信息1.2 控制turtlebot移动的三种方式1.2.1 命令行发布指令1.2.2 键盘操控1.2.3 Python脚本控制1.2.4 使用rqt工具界面&#xff0c;发布运动指令 二、里程计(odometry)TurtleBot3 仿真 进行实操之前&#xff0c;先准备环境 $ sud…...

G2406C是一款高效的直流-直流降压开关稳压器,能够提供高达1A输出电流。

G2406C 1.5MHz&#xff0c;1A高效降压DC-DC转换器 概述: G2406C是一款高效的直流-直流降压开关稳压器&#xff0c;能够提供高达1A输出电流。G2406C在2.7V至5.5V的宽范围输入电压下工作&#xff0c;使IC是低压电源转换的理想选择。在1.5MHz的固定频率下运行允许使用具有小电感…...

HTB——常见端口及协议总结

文章目录 一、 常见端口二、HTTP协议三、FTP四、SMB 一、 常见端口 http协议&#xff1a;80、8000https协议&#xff1a;443、8443ftp协议&#xff1a;20&#xff08;数据传输&#xff09;、21&#xff08;发送命令&#xff09;smb协议&#xff1a;445 二、HTTP协议 https的…...

Spring Boot中处理简单的事务

说到事务&#xff0c;我们第一影响应该是数据库管理系统的一个重要概念。 事务&#xff08;Transaction&#xff09;是数据库管理系统&#xff08;DBMS&#xff09;中的一个概念&#xff0c;用于管理对数据库的一组操作&#xff0c;这些操作要么全部成功执行&#xff0c;要么全…...

source activate my_env 和conda activate my_env 有什么区别

source activate my_env 和conda activate my_env 有什么区别 source activate 和 conda activate 是两个不同的命令&#xff0c;用于在Conda环境中激活特定的虚拟环境。它们的区别在于它们分别适用于不同版本的Conda。 source activate&#xff1a; source activate 是在Con…...

机器学习模型超参数优化最常用的5个工具包!

优化超参数始终是确保模型性能最佳的关键任务。通常&#xff0c;网格搜索、随机搜索和贝叶斯优化等技术是主要使用的方法。 今天分享几个常用于模型超参数优化的 Python 工具包&#xff0c;如下所示&#xff1a; scikit-learn&#xff1a;使用在指定参数值上进行的网格搜索或…...

出口美国操作要点汇总│走美国海运拼箱的注意事项│箱讯科技

01服务标准 美国的货物需要细致的服务&#xff0c;货物到港后的服务也是非常重要的。如果在货物到港15天内&#xff0c;如果没有报关行进行(PROCEED)&#xff0c;货物就会进入了G.O.仓库&#xff0c;G.O.仓库的收费标准是非常高的。 02代理资格审核 美国航线除了各家船公司&a…...

Gateway网关

Gateway网关 1、网关的位置与作用 官网&#xff1a;Spring Cloud Gateway Geteway是Zuul的替代&#xff0c; Zuul&#xff1a;路由和过滤Zuul最终还是会注册到Eureka Zuul网关采用同步阻塞模式不符合要求。 Spring Cloud Gateway基于Webflux&#xff0c;比较完美地支持异步…...

Python Opencv实践 - 车牌定位(纯练手,存在失败场景,可以继续优化)

使用传统的计算机视觉方法定位图像中的车牌&#xff0c;参考了部分网上的文章&#xff0c;实际定位效果对于我目前使用的网上的图片来说还可以。实测发现对于车身本身是蓝色、或是车牌本身上方有明显边缘的情况这类图片定位效果较差。纯练手项目&#xff0c;仅供参考。代码中im…...

U盘插在电脑上显示要格式化磁盘怎么办

U盘是一种便携式存储设备&#xff0c;广泛应用于各种场合。然而&#xff0c;有时候我们可能会遇到一些问题&#xff0c;比如将U盘插入电脑后显示要格式化磁盘&#xff0c;这通常意味着U盘的分区出现了问题或者U盘的文件系统已经损坏。这种情况下&#xff0c;我们应该如何解决呢…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...