当前位置: 首页 > 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;我们应该如何解决呢…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...