[pgrx开发postgresql数据库扩展]5.自定义函数与SQL组合应用

news2024/11/24 14:52:40

老规矩的声明:

并不是所有场景都需要(或者适合)用rust来写的,绝大部分操作数据库的功能和计算,用SQL就已经足够了!

本系列中,所有的案例,仅用于说明pgrx的能力,而并非是说这样做比用SQL更合适。反之:对于操作数据库本身的部分,大部分能用SQL来实现的东西,都比做一个扩展开发要更加合适。

——如果哪位大神写Rust走火入魔,说啥数据库功能都要用Rust来扩展实现的,不报我的名字,打成半死就行,报我的名字,请打成八成死。

上篇文章做的函数基本上独立使用的,今天我们来看看写好的扩展函数与SQL联合起来怎么来实现一个比较复杂的功能:

例如有以下这样一个场景:

我们需要评估一下公司有多少人已经学完了公司所有课程,可以毕业输出社会了,这样就需要进行如下统计: 假设截止到今年的12月30日:

  1. 年满35岁,而且在公司服务满10年的人有多少。
  2. 年满35岁,而且在公司服务超过5年,但是没有10年的人有多少。
  3. 年满35岁,在公司没有服务超过一年,但是没有5年的有多少?
  4. 年满35岁,入职没有超过一年的有多少?
  5. 不满35岁的,有多少?

反正一句话:

也就是说,需要把20万条记录,分成五类,然后统计数量,一般来说,这种简单的需求,用SQL就可以直接做了,如下所示:

还是那句话,我对SQL不是太熟,这写功能虽然可以实现,但是性能就不要要求了:

WITH graduate AS (
SELECT 
    CASE
    WHEN date_part('year',age('2023-12-30',birthday)) >= 35 
                    AND date_part('year',age('2023-12-30',indate)) >= 10
                    THEN  '35岁以上工作满10年'
    WHEN date_part('year',age('2023-12-30',birthday)) >= 35 
                    AND date_part('year',age('2023-12-30',indate)) >= 5
                    AND date_part('year',age('2023-12-30',indate)) < 10
        THEN  '35岁以上工作满5年不满10年'
    WHEN date_part('year',age('2023-12-30',birthday)) >= 35 
                    AND date_part('year',age('2023-12-30',indate)) >= 1
                    AND date_part('year',age('2023-12-30',indate)) < 5
        THEN  '35岁以上工作满1年不满5年'
    WHEN date_part('year',age('2023-12-30',birthday)) >= 35 
                    AND date_part('year',age('2023-12-30',indate)) < 1
        THEN  '35岁以上工作不满1年'
    
    WHEN date_part('year',age('2023-12-30',birthday)) < 35 
        THEN  '不满35岁'
    END as ga
FROM tab_emps)
SELECT ga,count(ga) FROM graduate
GROUP BY(ga);

计算结果如下:

可以看见,此类计算的输入和输出并不是1:1的,我们以前做数学计算,表中有20万条记录,计算出来,也是20万条记录,而我们这边在20万条记录的基础上,计算出来的是5条记录……

说那么多,不就是聚合么……

好吧,我们后面还会具体讲聚合函数的开发,这里我们用SRF的方式来实现这种操作。

代码如下:

//rust时间计算函数没有周年计算的能力,所以我自己写了一个 
//but 效率非常差……如果哪位大神知道如何高性能计算周年的话,请与我联系 
fn anniversary(now: &DateTime<Local>,date:&DateTime<Local>)-> i32{
    let month = now.month();  
    let day = now.day();  
    let month2 = date.month();  
    let day2 = date.day();  

    let mut year_a = now.year() - date.year();

    if month < month2{
        year_a -=1;
    }
    else if month == month2{
        if day < day2{
            year_a -=1;
        }
    }
    year_a
}

#[pg_extern]
fn cal_graduate(indate:pgrx::Date,birthday:pgrx::Date) -> &'static str{

    let now: DateTime<Local> = Local.with_ymd_and_hms(2023,12,30,23,59,59).unwrap();
    let dt1 = Local.timestamp_opt(indate.to_posix_time(), 0).unwrap();
    let dt2 = Local.timestamp_opt(birthday.to_posix_time(), 0).unwrap();
    
    let work_year = anniversary(&now,&dt1);
    let bir_year= anniversary(&now,&dt2);
    
    if bir_year >=35{
        if work_year >=10{
            "满35岁且工作满10年"
        }
        else if work_year >=5 && work_year< 10 {
            "满35岁且工作满5年但不满10年"
        }
        else if work_year >=1 && work_year < 5 {
            "满35岁且工作满1年但不满5年"
        }
        else{
            "满35岁且工作不满1年"
        }
    }
    else{
       "不满35岁"
    }
}

计算结果如下:

可以看见,pgrx开发的函数,能够与SQL一起组合,以实现更加方便、简洁的调用方式,当然,SQL更容易使用就是了。

不过因为Rust没有提供周年计算的方法,他只能计算unix时间差,所以各种闰年闰秒都出不来,结果只能我自己做一个很拉胯的周年算法,导致性能极糟糕……如下所示:

用SQL只要154ms,而我自己写的用了1703ms。。。10倍的差距有没有……

不过嘛:

就这样,打完收工。

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

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

相关文章

BPMN2.0 任务-用户任务

“用户任务(user task)”用于对需要人工执行的任务进行建模。当流程执行到达用户任务时,会为指派至该任务的用户或组的任务列表创建一个新任务。 用户任务用左上角有一个小用户图标的标准任务(圆角矩形)表示。 用户任务在XML中如下定义。其中id是必须属性,name是可选属性…

提高网络安全性:探索ADAudit Plus的全功能IT安全审计解决方案

网络安全一直是组织和企业需要关注的重要问题之一&#xff0c;因为随着企业数字化的加速和技术的不断发展&#xff0c;网络攻击的威胁也变得越来越严峻。因此&#xff0c;组织和企业需要采取措施保护其信息资产和网络安全。 ADAudit Plus是一种全功能的IT安全审计解决方案&…

2023年商票研究报告

第一章 行业概况 1.1 定义 商票是指出票人依托商业汇票系统&#xff0c;以数据电文形式制作的&#xff0c;委托付款人在指定日期无条件支付确定的金额给收款人或者持票人的票据。按承兑人的不同&#xff0c;商业汇票分为银行承兑汇票和商业承兑汇票&#xff08;即商票&#x…

flex布局 高度没有自动撑到max-height

在做一个项目时&#xff0c;用到了竖向flex布局&#xff0c;我写了max-height: 820px, 但是到小屏幕时&#xff0c;只能撑到773px&#xff0c;解决方法是height: max-content. 但是不知道为什么只能撑到773px便撑不动了。 https://zhuanlan.zhihu.com/p/130460207 这个文档说的…

workerman开发者必须知道的几个问题

1、windows环境限制 windows系统下workerman单个进程仅支持200个连接。 windows系统下无法使用count参数设置多进程。 windows系统下无法使用status、stop、reload、restart等命令。 windows系统下无法守护进程&#xff0c;cmd窗口关掉后服务即停止。 windows系统下无法在一个…

目标检测之损失函数

损失函数的作用为度量神经网络预测信息与期望信息&#xff08;标签&#xff09;的距离&#xff0c;预测信息越接近期望信息&#xff0c;损失函数值越小。 在目标检测领域&#xff0c;常见的损失分为分类损失和回归损失。 L1损失 L1 Loss也称为平均绝对值误差&#xff08;MAE&…

[HNCTF 2022 WEEK4]ezheap

Index 前言Checksec & IDA 前言 手把手教学&#xff0c;覆盖一切途中会遇到的问题。 [HNCTF 2022 WEEK4]ezheap Checksec & IDA 保护全开&#xff0c;但是四肢健全&#xff08;四项功能 增删改查&#xff09;&#xff0c;因此是ezheap。 主要来观察函数add和show。 d…

注意力机制:基于Yolov5/Yolov7的Triplet注意力模块,即插即用,效果优于cbam、se,涨点明显

论文&#xff1a;https://arxiv.org/pdf/2010.03045.pdf 本文提出了可以有效解决跨维度交互的triplet attention。相较于以往的注意力方法&#xff0c;主要有两个优点&#xff1a; 1.可以忽略的计算开销 2.强调了多维交互而不降低维度的重要性&#xff0c;因此消除了通道和权…

信号完整性分析基础知识之传输线和反射(三):仿真和测试反射波形

使用上面反射系数的定义&#xff0c;可以计算来自任意阻抗的反射信号。当终端阻抗为阻性元件时&#xff0c;阻抗恒定&#xff0c;反射电压容易计算。当终端具有更复杂的阻抗行为&#xff08;例如电容性或电感性终端&#xff0c;或两者的某种组合&#xff09;时&#xff0c;如果…

3.QT布局管理

布局管理系统 布局管理器 QLayout类继承图&#xff1a; 新建Qt Widgets项目mylayout&#xff0c;选择基类QWidget&#xff0c;类名MyWidget .ui拖用Font Combo Box、Text Edit&#xff0c;单击主界面&#xff0c;ctrlL&#xff0c;发现两个部件填满界面&#xff0c;运行后随…

Docker部署MySQL主从复制

文章目录 平台说明一、Docker创建网络二、创建MySQL主从容器1.拉取镜像2.查看镜像3.创建启动容器 三、主从配置1.主机配置文件2.从机配置文件3.注意事项4.重启容器5.连接主从数据库主机配置从机配置启动从机复制 四、测试主从复制 平台说明 操作系统&#xff1a;Windows 11 Do…

接口测试入门必会知识总结(学习笔记)

目录 什么是接口&#xff1f; 内部接口 外部接口 接口的本质 什么是接口测试&#xff1f; 反向测试 为什么说接口测试如此重要&#xff1f; 越接近底层的 Bug&#xff0c;影响用户范围越广 目前流行的测试模型 接口测试的优越性 不同协议形式的测试 接口测试工作场景…

『python爬虫』01. 爬虫入门的基础知识(保姆级图文)

目录 1. 合法性2. 爬虫原理3. 网站源代码查看4. 查看网络请求总结 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 1. 合法性 查看网站的爬虫协议&#xff0c;简单介绍爬虫协议robots.txt&#xff0c;避免爬虫爬的好…

简单理解内存分页机制

文章目录 1.CPU寻址方式2.段式内存访问的缺点3.80386两级页表4.PAE三级页表5.x64四级页表6.虚拟内存 思考一个问题&#xff1a;如果没有这样的分页机制时应用程序是怎么访问物理内存地址&#xff1f; 1.CPU寻址方式 Effective Address Base (Index * Scale) Displacement …

加载自己的图像数据集

文章目录 1 加载图像数据集2 图像预处理3 再次加载数据集4 这里还有一个问题&#xff0c;我们没有验证集5 构建DataLoader6 检查是否正确导入数据集 原文链接&#xff1a;《加载自己的图像数据集》 ​ 数据集下载链接 1 加载图像数据集 目录结构&#xff1a; 针对这种非常典型…

Java+proj4j实现根据EPSG编码进行坐标系转换

场景 JavaGeoTools实现WKT数据根据EPSG编码进行坐标系转换&#xff1a; JavaGeoTools实现WKT数据根据EPSG编码进行坐标系转换_霸道流氓气质的博客-CSDN博客 上面使用GeoTools实现坐标系转换。 VueOpenlayersproj4实现坐标系转换: VueOpenlayersproj4实现坐标系转换_霸道流…

VUE3页面div点击改变样式

如题目所示。 用上VUE之后&#xff0c;前后端分离&#xff0c;组件式开发&#xff0c;代码复用、独立性和隔离性都挺好&#xff0c;可维护性得以提高。相比之下&#xff0c;以前用jQuery&#xff0c;代码实在太多了。 不过&#xff0c;vue有个地方不大好&#xff0c;就是控制…

算法基础(二)(共有30道例题)

六、数据结构 &#xff08;一&#xff09;数组 定义&#xff1a;数组是存放在连续内存空间上的相同类型数据的集合。数组可以方便的通过下标索引的方式获取到下标下对应的数据。 注意&#xff1a; &#xff08;1&#xff09;数组下标都是从0开始的。 &#xff08;2&#xff0…

【SWAT水文模型】SWAT水文模型建立及应用第二期:土地利用数据的准备(待更新)

SWAT水文模型建立及应用&#xff1a;土地利用数据的准备 1 简介2 土地利用数据的下载1.1 数据下载方式1.2 数据下载 2 土地利用数据的准备2.1 矢量转栅格2.2 土地利用类型的重分类2.3 土地利用分布图投影调整2.4 土地利用类型索引表建立 参考 SWAT水文模型建立及应用第一期主要…

前苹果设计总监创办,Humane想用AI+AR界面取代手机

在2001年&#xff0c;微软研究院一位工程师Gordon Bell开始了一段长时间的“生活记录”&#xff08;Lifelogging&#xff09;之旅&#xff0c;他会在胸前、头顶或是眼镜腿处佩戴相机&#xff0c;每30秒自动拍摄一张照片&#xff0c;以捕捉自己生命中的瞬间&#xff0c;记录下他…