记一次postgresql拼接函数string_agg() 和row_number() 使用

news2024/12/26 21:01:22

PG两个函数使用需求和简单介绍

  • 需求背景介绍
    • 第一个需求背景是这样的
    • 需求升级一下
    • 接下来讲讲STRING_AGG()
      • 基本语法
      • 排序
    • 然后我们再说说ROW_NUMBER()
      • 基本语法
      • 使用 row_number() over (partition by) 进行分组统计
      • 使用 row_num限定每组数量

需求背景介绍

第一个需求背景是这样的

我需要从数据库查询企业的一些信息,其中包括企业曾用名,企业曾用名可能有多个,但是企业主体信息只有一个,且不在同一张表中;我还需要取出另一个表中关联的电话和邮箱,其中电话和邮箱有多个,实际为年份不同可能不一样,也可能为空,我需要取不为空的最新年份的数据。
数据库PG,要求所有曾用名,分隔,企业查询为模糊查询。

SELECT
            C.entname as entname,
            C.uniscid as uniscid,
            cb.dom as dom,
            cb.esdate as esdate,
            cb."name" as frname,
            cb.regcap as regcap,
            STRING_AGG ( cm.altbe, ',' ) as nameBefore,
            A.email as email,
            A.tel as tel,
            co.name as entstatus
        FROM
            company
            C LEFT JOIN company_basic cb ON C.entid = cb.entid
            LEFT JOIN company_modify cm ON C.entid = cm.entid
            left join code_ex02 co on cb.entstatus = co.code
            LEFT JOIN (
        SELECT
            cc.entid AS entid,
            ca.email AS email,
            ca.tel AS tel,
            ROW_NUMBER () OVER ( PARTITION BY cc.ID ORDER BY ca.email DESC ) AS rn
        FROM
            company cc
            LEFT JOIN company_ar ca ON cc.entid = ca.entid
        WHERE
            cc.entname LIKE concat('%',#{companyName},'%')
            AND ca.email IS NOT NULL
            AND ca.tel IS NOT NULL
        ORDER BY
            ca.ancheyear DESC
            ) A ON C.entid = A.entid AND A.rn = 1
        WHERE
            C.entname LIKE concat('%',#{companyName},'%')
            AND cm.altitem = '01'
        GROUP BY
            C.entname,
            C.uniscid,
            cb.dom,
            cb.esdate,
            cb."name",
            cb.regcap,
            A.email,
            A.tel,
            co.name

可以看到,关联company_ar表,查曾用名,需要使用row_number()函数,取第一行,这就需要先包一层,取rn=1
这里为什么不能使用limit 1,原因是这里是模糊查询,查出来的是多家公司,我需要每个公司取第一行,limit 1不能满足。


需求升级一下

我需要从数据库查询企业的一些信息,其中包括企业曾用名,企业曾用名可能有多个,且是分开的,数据大概像下图
既有可能有多个,每个还都是分开的,需要拼接,每个完整的企业曾用名使用,分隔,但是企业主体信息只有一个,且不在同一张表中;我还需要取出另一个表中关联的电话和邮箱,其中电话和邮箱有多个,实际为年份不通可能不一样,也可能为空,我需要取不为空的最新年份的数据。
数据库PG,要求所有曾用名先按照id排序之后拼接再,分隔,企业查询为模糊查询。

在这里插入图片描述

SELECT
            C.entname as entname,
            C.uniscid as uniscid,
            C.dom as dom,
            C.esdate as esdate,
            C."name" as frname,
            C.regcap as regcap,
            STRING_AGG ( C.content_text, ',' ) as nameBefore,
            C.email as email,
            C.tel as tel,
            c.entstatus as entstatus
        FROM
            (
        SELECT
            C.entname,
            C.uniscid,
            cb.dom,
            cb.esdate,
            cb."name",
            cb.regcap,
            STRING_AGG ( ccrc.content_text, '' ORDER BY ccrc.ID ) AS content_text,
            A.email,
            A.tel,
            cb.entstatus as entstatus
        FROM
            company
            C LEFT JOIN company_basic cb ON C.ID = cb.entid
            LEFT JOIN company_change_record ccr ON ccr.entid = C.ID
            AND ccr.altitem = '名称变更'
            LEFT JOIN company_change_record_content ccrc ON ccr.ID = ccrc.company_change_record_id
            AND ccrc.company_chang_type = 0
            LEFT JOIN (
        SELECT
            cc.ID AS ID,
            ca.email AS email,
            ca.tel AS tel,
            ROW_NUMBER () OVER ( PARTITION BY cc.ID ORDER BY ca.email DESC ) AS rn
        FROM
            company cc
            LEFT JOIN company_ar ca ON cc.ID = ca.entid
        WHERE
            cc.entname LIKE concat('%',#{companyName},'%')
            AND ca.ancheyear IS NOT NULL
            AND ca.email IS NOT NULL
            AND ca.tel IS NOT NULL
        ORDER BY
            ca.ancheyear DESC
            ) A ON A.ID = C.ID
            AND A.rn = 1
        WHERE
            C.entname LIKE concat('%',#{companyName},'%')
        GROUP BY
            C.entname,
            C.uniscid,
            cb.dom,
            cb.esdate,
            cb."name",
            cb.regcap,
            A.email,
            A.tel,
            cb.entstatus,
            ccrc.company_change_record_id
            ) C
        GROUP BY
            C.entname,
            C.uniscid,
            C.dom,
            C.esdate,
            C."name",
            C.regcap,
            C.email,
            C.tel,
            c.entstatus

这个sql写起来就比之前的sql又多一层,曾用名字段需要拼接两次,且企业曾用名拼接是需要按照id排序的。

接下来讲讲STRING_AGG()

基本语法

string_agg(column_name, separator)  

前边column_name是想要拼接的字段名,后边separator是分隔符。
像上边sql中

STRING_AGG ( C.content_text, ',' )

将content_text 以,分隔
使用像string_agg() 聚合函数,需要使用group by将不需要聚合的字段都写在group by中。

排序

这里升级版需求需要排序然后再聚合拼接,就需要加上order by
这里直接在函数中加上就可以

STRING_AGG ( ccrc.content_text, '' ORDER BY ccrc.ID )

这样就可以实现。

然后我们再说说ROW_NUMBER()

row_number() 函数是 PostgreSQL 中的一个窗口函数,它的作用是为每一行分配一个唯一的序号。当涉及到分组统计时,我们可以使用 row_number() 函数结合 over (partition by) 子句来实现。

基本语法

ROW_NUMBER() OVER (
    [PARTITION BY partition_expression, ... ]
    ORDER BY sort_expression [ASC | DESC], ...
)

partition_expression需要是唯一ID,order by 按照自己的实际需求

使用 row_number() over (partition by) 进行分组统计

像上边sql中,

ROW_NUMBER () OVER ( PARTITION BY cc.ID ORDER BY ca.email DESC 

我们首先使用 PARTITION BY cc.ID 对数据进行分组,然后使用 ORDER BY email DESC 对每个分组内的数据按照邮箱(其实是随便选的,因为这里需求不做强制要求)降序排序。接着,我们使用 ROW_NUMBER() 函数为每一行分配一个唯一的序号。最后,我们将结果输出到一个新的表中。

使用 row_num限定每组数量

像上边sql中,已经对结果进行了分组统计

ROW_NUMBER () OVER ( PARTITION BY cc.ID ORDER BY ca.email DESC 

最终关联的时候取rn = 1,就可以限定数量,这里可以使用<= 等等限定数量。

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

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

相关文章

6、组件通信详解(父子、兄弟、祖孙)

一、父传子 1、props 用法&#xff1a; &#xff08;1&#xff09;父组件用 props绑定数据&#xff0c;表示为 v-bind:props"数据" &#xff08;v-bind:简写为 : &#xff0c;props可以任意命名&#xff09; &#xff08;2&#xff09;子组件用 defineProps([props&…

curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL

source ~/.bash_profile flutter clean Command exited with code 128: git fetch --tags Standard error: 错误&#xff1a;RPC 失败。curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8) 错误&#xff1a;预期仍然需要 2737 个字节的正文 fetch-pack: unexpec…

力扣167. 两数之和 II - 输入有序数组

Problem: 167. 两数之和 II - 输入有序数组 文章目录 题目描述思路复杂度Code 题目描述 思路 1.定义左、右指针left、right分别指向数组索引为0和索引为nums.length - 1&#xff0c;定义结果数组int[] res new int[2]用于存储索引; 2.查找&#xff1a;当判断numbers[left] nu…

质量小议38 -- 60岁退休的由来

总是要有个标准&#xff0c;质量更是如些。 标准不是固定不变的&#xff0c;与时俱进。 关键词&#xff1a;当时的人均寿命&#xff1b;渐进式 60岁退休。 22大学毕业开始工作&#xff08;当然可能会更早&#xff09;&#xff0c;到60岁退休&#xff0c;要工作38年。 …

linux:如何硬盘分区扩容

文章目录 1. 前言2. 硬盘分区2.1 查看硬盘2.2 分区2.3 格式化 3. 硬盘分区扩容3.1 创建物理卷3.2 扩展到卷组&#xff08;volume group&#xff09;3.3 合并到待拓展分区3.4 使扩展生效 4 .参考 1. 前言 本文介绍如何将剩余的空间扩展到已有的硬盘分区中。 安装虚拟机的教程&…

【传知代码】BLIP - VLP任务的新框架(论文复现)

前言&#xff1a;在当今人工智能与机器学习领域&#xff0c;视觉-语言预训练&#xff08;Vision-and-Language Pre-training, VLP&#xff09;任务正逐渐崭露头角&#xff0c;其对于推动跨模态智能系统的进步起着至关重要的作用。在这些系统中&#xff0c;图像与文本不再是孤立…

vue -ant -design 卡片是布局 实现动态计算 当前的 左右间距 实现居中

是这样的一个样式 我们使用display :flex 布局的时候 我们全部剧中 display: flex;align-items: center;justify-content: center; 如果是上述的代码来说的话 总是最后的一个也是会居中的 这样就比较丑 我们好像就没有什么好的办法了 我们这自己写的 肯定没有组件牛 如果有…

【Redis学习笔记04】Jedis客户端(上)

Java客户端操作Redis Java生态丰富&#xff0c;自定义的客户端非常多&#xff0c;常见的有Jedis、Lettuce、以及Spring整合后的RedisTemplate&#xff0c;但是对于初学者而言&#xff0c;从Jedis开始入门学习是非常容易上手的&#xff0c;因为Jedis中的API与原生Redis命令高度…

基于栅格占据概率和距离场的机器人覆盖轨迹模拟

基于栅格占据概率和距离场的机器人覆盖轨迹模拟 简介 辐射场模型实现 理论基础 指数函数建模 我们使用指数函数来表示机器人在某个栅格上停留时间对覆盖概率的影响: p ( t ) 1 − e − λ t p(t) 1 - e^{-\lambda t} p(t)1−e−λt 其中 λ \lambda λ 是控制增长速率…

java线程相关知识点

Java多线程涉及以下几个关键点 1.线程生命周期&#xff1a;理解线程从创建到销毁的各个阶段&#xff0c;包括新建、运行、阻塞、等待、计时等待和终止。 2.线程同步&#xff1a;掌握如何使用synchronized关键字和Lock接口来同步代码&#xff0c;防止数据竞争和死锁。 3.线程间通…

vivado HW_DEVICE

硬件设备 描述 在Vivado Design Suite的硬件管理器功能中&#xff0c;每个硬件目标都可以 具有一个或多个Xilinx FPGA设备进行编程或用于调试目的。这个 hw_device对象是通过hw_server打开的hw_target上的物理部分。这个 current_hw_device命令指定或返回当前设备。 相关对象 硬…

Linux系统编程(十二)线程同步、锁、条件变量、信号量

线程同步&#xff1a; 协同步调&#xff0c;对公共区域数据按序访问。防止数据混乱&#xff0c;产生与时间有关的错误。数据混乱的原因 一、互斥锁/互斥量mutex 1. 建议锁&#xff08;协同锁&#xff09;&#xff1a; 公共数据进行保护。所有线程【应该】在访问公共数据前先拿…

Vue3 + TS + Antd + Pinia 从零搭建后台系统(一) 脚手架搭建 + 入口配置

简易后台系统搭建开启&#xff0c;分几篇文章更新&#xff0c;本篇主要先搭架子&#xff0c;配置入口文件等目录 效果图一、搭建脚手架&#xff1a;二、处理package.json基础需要的依赖及运行脚本三、创建环境运行文件四、填充vue.config.ts配置文件五、配置vite-env.d.ts使项目…

微服务开发与实战Day04 - 网关路由和配置

一、网关路由 网关&#xff1a;就是网络的关口&#xff0c;负责请求的路由、转发、身份校验。 在SpringCloud中网关的实现包括两种&#xff1a; 1. 快速入门 Spring Cloud Gateway 步骤&#xff1a; ①新建hm-gateway模块 ②引入依赖pom.xml(hm-gateway) <?xml version…

【python】OpenCV GUI——Trackbar(14.2)

学习来自 OpenCV基础&#xff08;12&#xff09;OpenCV GUI中的鼠标和滑动条 文章目录 GUI 滑条介绍cv2.createTrackbar 介绍牛刀小试 GUI 滑条介绍 GUI滑动条是一种直观且快速的调节控件&#xff0c;主要用于改变一个数值或相对值。以下是关于GUI滑动条的详细介绍&#xff1a…

course-nlp——6-rnn-english-numbers

本文参考自https://github.com/fastai/course-nlp。 使用 RNN 预测数字的英文单词版本 在上一课中&#xff0c;我们将 RNN 用作语言模型的一部分。今天&#xff0c;我们将深入了解 RNN 是什么以及它们如何工作。我们将使用尝试预测数字的英文单词版本的问题来实现这一点。 让…

Llama模型家族之Stanford NLP ReFT源代码探索 (三)reft_model.py代码解析

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

C# WPF入门学习主线篇(十七)—— UniformGrid布局容器

C# WPF入门学习主线篇&#xff08;十七&#xff09;—— UniformGrid布局容器 欢迎来到C# WPF入门学习系列的第十七篇。在前几篇文章中&#xff0c;我们已经探讨了 Canvas、StackPanel、WrapPanel、DockPanel 和 Grid 布局容器及其使用方法。本篇博客将介绍另一种非常实用且简单…

推荐三款你不知道的良心软件

Tico——抠图、拼图软件 抠图软件大家见过很多了把&#xff0c;但是从多张图片中抠出来的图片拼接成一张图片你们很少见过吧。 Tico就是一款将抠出来的图片拼接成一张新图片的软件&#xff0c;目前仅支持IOS平台。 Tico拼贴图提供了强大的图像编辑和处理功能&#xff0c;用户…

预期值与实际值对比

编辑实际值和预期值变量 因为在单独的代码当中&#xff0c;我们先定义了变量str&#xff0c;所以在matcher时传入str参数&#xff0c;但当我们要把这串代码写在testrun当中&#xff0c;改下传入的参数&#xff0c;与excel表做连接 匹配的结果是excel表中的expect结果&#xf…