postgresql-通用表表达式

news2024/11/28 14:53:14

postgresql-通用表表达式

  • 简介
  • 简单 CTE
  • 递归 CTE
    • 案例1
    • 案例2
  • DML 语句与 CTE

简介

通用表表达式(Common Table Expression、CTE)是一个临时的查询结果或者临时表,可以
在其他 SELECT、INSERT、UPDATE 以及 DELETE 语句中使用。通用表表达式只在当前语句中
有效,类似于子查询。
使用 CTE 的主要好处包括:

  • 提高复杂查询的可读性。CTE 可以将复杂查询模块化,组织成容易理解的结构
  • 支持递归查询。CTE 通过引用自身实现递归,可以方便地处理层次结构数据和图数据。

简单 CTE

通用表表达式的定义如下:

WITH cte_name (col1, col2, ...) AS (
 cte_query_definition
)
sql_statement;

在这里插入图片描述
PostgreSQL 中的 CTE 通常用于简化复杂的连接查询或子查询。例如:

with department_avg(department_id, avg_salary) as (
 select department_id,
 avg(salary) as avg_salary
 from employees
 group by department_id
)
select d.department_name,
 da.avg_salary
 from departments d
 join department_avg da
 on (d.department_id = da.department_id)
order by d.department_name;

在这里插入图片描述
首先,我们定义了一个名为 department_avg 的 CTE,表示每个部门的平均月薪;然后和
departments 表进行连接查询。虽然用其他方式也可以实现相同的功能,但是 CTE 让代码显得更
加清晰易懂。

一个 WITH 关键字可以定义多个 CTE,而且后面的 CTE 可以引用前面的 CTE。例如:

with cte1(n) as (
 select 1
),
cte2(m) as (
 select n+1 from cte1
)
select *
 from cte1, cte2;

在这里插入图片描述
以上示例中定义了两个 CTE,其中 cte2 引用了 cte1。最后的查询使用两者进行连接查询。

递归 CTE

递归 CTE 允许在它的定义中进行自引用,理论上来说可以实现任何复杂的计算功能,最常
用的场景就是遍历层次结构的数据和图结构数据。

WITH RECURSIVE cte_name AS(
 cte_query_initial -- 初始化部分
 UNION [ALL]
 cte_query_iterative -- 递归部分
) SELECT * FROM cte_name;

RECURSIVE 表示递归;
cte_query_initial 是初始化查询,用于创建初始结果集
cte_query_iterative 是递归部分,可以引用 cte_name
如果递归查询无法从上一次迭代中返回更多的数据,将会终止递归并返回结果。

案例1

一个经典的递归 CTE 案例就是生成数字序列:

with recursive t(n) as (
 values (1)
 union all
 select n+1 from t where n < 10
)
select n from t;

在这里插入图片描述
以上语句执行过程如下:

  • 执行 CTE 中的初始化查询,生成一行数据(1)
  • 第一次执行递归查询,判断 n < 10 成立,生成一行数据 2 (n+1);
  • 重复执行递归查询,生成更多的数据;直到 n = 10 终止;此时临时表 t 中包含 10 条数据
  • 执行主查询,返回所有的数据

如果没有指定终止条件,上面的查询将会进入死循环

案例2

递归 CTE 遍历组织结构

with recursive employee_path (employee_id, employee_name, path) as
(
 select employee_id, concat(first_name, ',', last_name), concat(first_name,
',', last_name) as path
 from employees
 where manager_id is null
 union all
 select e.employee_id, concat(e.first_name, ',', e.last_name),
concat(ep.path, '->', e.first_name, ',', e.last_name)
 from employee_path ep
 join employees e on ep.employee_id = e.manager_id
)
select employee_name, path
 from employee_path
order by employee_id;

在这里插入图片描述
其中,初始化查询语句返回了公司最高层的领导(manager_id IS NULL),也就是
“Steven,King”;递归查询将员工表的 manager_id 与已有结果集中的 employee_id 关联,获取每个
员工的下一级员工,直到无法找到新的数据;path 字段存储了每个员工从上至下的管理路径

更多关于递归 CTE 的实际应用场景,可以参考这篇文章

DML 语句与 CTE

除了 SELECT 语句之外,INSERT、UPDATE 或者 DELETE 语句也可以与 CTE 一起使用。
我们可以在 CTE 中使用 DML 语句,也可以将 CTE 用于 DML 语句。
如果在 CTE 中使用 DML 语句,我们可以将数据修改操作影响的结果作为一个临时表,然
后在其他语句中使用。例如:

-- 创建一个员工历史表
create table employees_history
as select * from employees where 1 = 0;
with deletes as (
 delete from employees
 where employee_id = 206
 returning *
)
insert into employees_history
select * from deletes;

SELECT employee_id, first_name, last_name
FROM employees_history;

在这里插入图片描述
我们首先创建了一个记录员工历史信息的 employees_history 表;然后使用 DELETE 语句定
义了一个 CTE,RETURNING *返回了被删除的数据,构成了结果集 deletes;然后使用 INSERT
语句记录被删除的员工信息

接下来我们将该员工添加回员工表:

WITH inserts AS (
 INSERT INTO employees
 VALUES
(206,'William','Gietz','WGIETZ','515.123.8181','2002-06-07','AC_ACCOUNT',8800.00,NULL,205,110)
 RETURNING *
)
INSERT INTO employees_history
SELECT * FROM inserts;

除了插入数据到 employees 表之外,我们还利用 CTE 在表 employees_history 中增加了一条
历史记录,现在该表中有两条数据
在这里插入图片描述
在这里插入图片描述
CTE 中的 UPDATE 语句有些不同,因为更新的数据分为更新之前的状态和更新之后的状态。
例如:

DELETE FROM employees_history;-- 清除历史记录
with updates as (
 update employees
 set salary = salary + 500
 where employee_id = 206
 returning *
)
insert into employees_history
select * from employees where employee_id = 206;
select employee_id, salary from employees_history;

在这里插入图片描述
returning 在 CTE 中,UPDATE 语句修改了一个员工的月薪;但是为了记录修改之前的数据,
我们插入 employees_history 的数据仍然来自 employees 表。因为在一个语句中,所有的操作都在
一个事务中,所以主查询中的 employees 是修改之前的状态。
如果想要获取更新之后的数据,直接使用 updates 即可:

with updates as (
 update employees
 set salary = salary - 500
 where employee_id = 206
 returning *
)
select employee_id,first_name, last_name, salary
from updates;

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/952104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关闭jenkins插件提醒信息

jenkins提醒信息和安全警告可以帮助我们了解插件或者jenkins的更新情况&#xff0c;但是有些插件是已经不维护了&#xff0c;提醒却一直存在&#xff0c;看着糟心&#xff0c;就像下面的提示 1、关闭插件提醒 找到如下位置&#xff1a;系统管理-系统配置-管理监控配置 打开管…

SQL注入 - POST注入方法

文章目录 注入流程正常尝试弱口令登录判断是否存在注入&#xff0c;是否会将用户输入拼接到sql语句&#xff0c;并当做代码执行尝试是否需要闭合语句尝试注释掉后面得语句判断字段数判断显错位判断当前数据库名判断当前数据库下的表名判断当前数据库下users表的列名获取usernam…

DHCP中继实验

文章目录 一、实验背景与目的二、实验拓扑三、实验需求四、实验解法1. 配置IP地址2.配置R1为DHCP服务器&#xff0c;能够跨网段为192.168.2.0/24网段自动分配IP地址3. 在PC3上Ping 192.168.1.1&#xff0c;确认可以Ping通 摘要&#xff1a; 本实验旨在通过配置DHCP中继实现跨网…

stm32---用外部中断实现红外接收器

一、红外遥控的原理 红外遥控是一种无线、非接触控制技术&#xff0c;具有抗干扰能力强&#xff0c;信息传 输可靠&#xff0c;功耗低&#xff0c;成本低&#xff0c;易实现等显著优点&#xff0c;被诸多电子设备特别是 家用电器广泛采用&#xff0c;并越来越多的应用到计算机系…

电缆工厂 3D 可视化管控系统 | 智慧工厂

近年来&#xff0c;我国各类器材制造业已经开始向数字化生产转型&#xff0c;使得生产流程变得更加精准高效。通过应用智能设备、物联网和大数据分析等技术&#xff0c;企业可以更好地监控生产线上的运行和质量情况&#xff0c;及时发现和解决问题&#xff0c;从而提高生产效率…

2023-8-30 八数码(BFS)

题目链接&#xff1a;八数码 #include <iostream> #include <algorithm> #include <unordered_map> #include <queue>using namespace std;int bfs(string start) {string end "12345678x";queue<string> q;unordered_map<strin…

[ZenTao]源码阅读:自定义任务类型

1、module/custom/control.php 2、module/custom/model.php

线性代数的学习和整理13: 定义域,值域,到达域 和单射,满射,双射,反函数,逆矩阵

目录 1 函数与 向量/矩阵 2 初等数学的函数 2.1 函数 2.2 函数的定义&#xff1a;定义域 →映射→ 值域 3 高等数学里的函数&#xff1a;定义域和陪域/到达域&#xff08;非值域&#xff09;的映射关系 3.1 函数 3.2 单射&#xff0c;满射&#xff0c;双射等都是针对…

整流二极管 DL4001~DL4007:1000V 1A

国产二极管品牌厂家东沃电子&#xff08;DOWOSEMI&#xff09;推出的整流二极管种类繁多、封装多样、型号齐全&#xff0c;根据正向电流大小来分&#xff0c;有&#xff1a;1A、1.5A、2A、3A、5A、6A、10A等等。关于整流二极管&#xff0c;之前东沃电子科普过很多这方面的知识和…

前端自学总结

文章目录 一、nodejs1.1、npm配置命令别名 二、JavaScript2.1、javascript注释 一、nodejs 1.1、npm配置命令别名 我们可以使用“node index.js”的方式运行代码 也可以利用npm配置别名的方式运行代码 在package.json中配置别名&#xff0c;利用“npm run 别名”也可以运行 st…

5000字详解OpenAI超级对齐四年计划:定义、挑战与方法

导读 超级智能是一把双刃剑&#xff0c;有助于解决许多重要问题&#xff0c;同时也可能削弱人类的权力并威胁我们的安全。为了治理这些风险&#xff0c;急需建立新的治理机构并解决AI模型的对齐问题。OpenAI于今年7月首次提出超级对齐的概念&#xff0c;并宣布投入20%的计算资源…

【CSS】简记CSS效果:通过transition(动画过渡属性)实现侧边栏目滑入滑出

需求 在资金明细的页面中&#xff0c;点击按钮时筛选区域从左侧滑出&#xff0c;完成筛选点击确认后调用接口完成数据查询&#xff0c;筛选区域滑入左侧&#xff1b; 基于微信小程序页面实现 wxml代码 <view><!-- 操作按钮 --><button type"primary&qu…

Matlab图像处理-图像旋转

基本概念 图像的旋转变换属于图像的位置变换&#xff0c;通常是以图像的中心为原点&#xff0c;将图像上的所有像素都旋转一个相同的角度。旋转后&#xff0c;图像的大小一般会改变。图像的旋转变换是指以图像的中心为原点&#xff0c;将图像上的所有像素都旋转同一个角度的变…

十、桥接模式

一、什么是桥接模式 桥接&#xff08;Bridge&#xff09;模式的定义如下&#xff1a;将抽象与实现分离&#xff0c;使它们可以独立变化。它是用组合关系代替继承关系来实现&#xff0c;从而降低了抽象和实现这两个可变维度的耦合度。 桥接&#xff08;Bridge&#xff09;模式包…

浅析token

上一章节我们学习了cookie和session机制&#xff0c;但是他们都有一些缺点&#xff0c;所有这次我们来了解一个机制---token。 一、cookie和session的缺点 cookie信息存储在客户端浏览器上&#xff0c;安全性较低&#xff0c;所以浏览器加入了一些限制确保cookie不会被恶意使用…

对称二叉树判断

目录 题目题目要求示例 解答方法一、实现思路时间复杂度和空间复杂度代码 方法二、实现思路时间复杂度和空间复杂度代码 题目 对称二叉树判断 题目要求 题目链接 示例 解答 方法一、 递归法 实现思路 使用到了判断两棵二叉树是否相等的方法&#xff0c;只不过对称二叉树…

扫盲:常用NoSQL数据库

前言 关系型数据库产品很多&#xff0c;如 MySQL、Oracle、Microsoft SQL Sever 等&#xff0c;但它们的基本模型都是关系型数据模型。 非关系型数据库又称为&#xff1a;NoSQL &#xff0c;没有统一的模型&#xff0c;而且是非关系型的。 常见的 NoSQL 数据库包括键值数据库、…

【Dots之006】PostTransformMatrix基础知识

一、基础介绍 PostTransformMatrix是一个组件&#xff1b;它用于不同比例对象的一个矩阵变换组件&#xff1b;当在Suscene中对GameObject比例变更的时候会发现以下情况&#xff1a; 1、当Gameobject的比例不相同的时候&#xff0c;在Entity Backing Previes窗口中可以看到已经…

0102阿里云配置3台ECS服务器-大数据学习

文章目录 1 前言1 配置VPC和子网2 创建安全组3 创建云服务器ECS3.1 规划配置3.2 配置 4 xshell连接服务器5 配置基础环境5.1 主机名映射5.2 ssh免密登录5.3 jdk 6 问题集6.1 Permission denied (publickey,gssapi-keyex,gssapi-with-mic).6.2 用tar解压文件出现错误Not found i…

video标签在安卓手机内置浏览器上的播放问题

道阻且长&#xff0c;行而不辍&#xff0c;未来可期 问题: 在手机内置浏览上&#xff0c;虽然没有给video标签设置controls,但在内置浏览器上&#xff0c;就是会显示。 而且&#xff0c;video一旦自动播放&#xff0c;video的层级就会提升到最前&#xff0c;想设置一个盒子覆盖…