有同事问我是否可以用一条SQL实现以下需求:社保缴存在换工作时可能会有中断,现在需要查询出每个人连续缴存起始月、终止月和月数,如果有中断需要把多个分段同时求出,这个可以使用PG的窗口函数实现,下面给出一个具体的实例。
创建测试表test,总共4个字段,name为姓名,jfyear社保缴存的年份,jfmonth社保缴存的月份,ispay是否已缴存(值为“已到账”代表已缴存,其它值为未缴存)。
postgres=# CREATE TABLE test(name VARCHAR(64),jfyear VARCHAR(4),jfmonth VARCHAR(2),ispay VARCHAR(3)); CREATE TABLE
复制
postgres=# INSERT INTO test postgres-# (NAME, jfyear, jfmonth, ispay) postgres-# VALUES postgres-# ('张三', '2020', '05', '未到账'), postgres-# ('张三', '2020', '04', '已到账'), postgres-# ('张三', '2020', '03', '已到账'), postgres-# ('张三', '2020', '02', '已到账'), postgres-# ('张三', '2020', '01', '已到账'), postgres-# ('张三', '2019', '12', '已到账'), postgres-# ('张三', '2019', '11', NULL), postgres-# ('张三', '2019', '10', '未到账'), postgres-# ('张三', '2019', '09', '已到账'), postgres-# ('李四', '2020', '05', NULL), postgres-# ('李四', '2020', '04', '已到账'), postgres-# ('李四', '2020', '03', '已到账'), postgres-# ('李四', '2020', '02', NULL), postgres-# ('李四', '2020', '01', '已到账'), postgres-# ('李四', '2019', '12', '已到账'), postgres-# ('李四', '2019', '11', NULL), postgres-# ('李四', '2019', '10', '未到账'), postgres-# ('李四', '2019', '09', '已到账'), postgres-# ('李四', '2019', '08', '已到账'), postgres-# ('李四', '2019', '07', '已到账'), postgres-# ('李四', '2019', '06', '已到账'); INSERT 0 21 postgres=# SELECT * FROM test; name | jfyear | jfmonth | ispay ------+--------+---------+-------- 张三 | 2020 | 05 | 未到账 张三 | 2020 | 04 | 已到账 张三 | 2020 | 03 | 已到账 张三 | 2020 | 02 | 已到账 张三 | 2020 | 01 | 已到账 张三 | 2019 | 12 | 已到账 张三 | 2019 | 11 | 张三 | 2019 | 10 | 未到账 张三 | 2019 | 09 | 已到账 李四 | 2020 | 05 | 李四 | 2020 | 04 | 已到账 李四 | 2020 | 03 | 已到账 李四 | 2020 | 02 | 李四 | 2020 | 01 | 已到账 李四 | 2019 | 12 | 已到账 李四 | 2019 | 11 | 李四 | 2019 | 10 | 未到账 李四 | 2019 | 09 | 已到账 李四 | 2019 | 08 | 已到账 李四 | 2019 | 07 | 已到账 李四 | 2019 | 06 | 已到账 (21 rows)
复制
postgres=# SELECT name, postgres-# e AS start_mon, --连续数的开始月份 postgres-# lead(s, 1, maxn) over(PARTITION BY name ORDER BY e) end_mon, --连续数的结束月份 postgres-# extract(YEAR FROM age(to_date(lead(s, 1, maxn) over(PARTITION BY name ORDER BY e), 'yyyymm'), to_date(e, 'yyyymm'))) * 12 + postgres-# extract(MONTH FROM age(to_date(lead(s, 1, maxn) over(PARTITION BY name ORDER BY e), 'yyyymm'), to_date(e, 'yyyymm'))) + 1 mons --此连续段连续缴存总月份数 postgres-# FROM (SELECT name, postgres(# lag(jfyear || jfmonth, 1) over(PARTITION BY name ORDER BY jfyear || jfmonth) s, --偏移查询,查询当前行前一行数据 postgres(# jfyear || jfmonth e, --拼接年月 postgres(# MAX(jfyear || jfmonth) over(PARTITION BY name) maxn --查询每个人最大的缴存月份 postgres(# FROM test postgres(# WHERE ispay = '已到账') a --查询已缴存月份,这样就会产生分段 postgres-# WHERE coalesce(age(to_date(e, 'yyyymm'), to_date(s, 'yyyymm')) - INTERVAL '1 mon', INTERVAL '1 mon') <> INTERVAL '00:00:00' --这里是关键,过滤掉连续的数据行 postgres-# ORDER BY name,e; name | start_mon | end_mon | mons ------+-----------+---------+------ 李四 | 201906 | 201909 | 4 李四 | 201912 | 202001 | 2 李四 | 202003 | 202004 | 2 张三 | 201909 | 201909 | 1 张三 | 201912 | 202004 | 5 (5 rows)
复制
最后修改时间:2020-06-29 15:33:11
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
外国CTO也感兴趣的开源数据库项目——openHalo
小满未满、
511次阅读
2025-04-21 16:58:09
9.9 分高危漏洞,尽快升级到 pgAdmin 4 v9.2 进行修复
严少安
357次阅读
2025-04-11 10:43:23
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
337次阅读
2025-04-15 14:48:05
openHalo问世,全球首款基于PostgreSQL兼容MySQL协议的国产开源数据库
严少安
311次阅读
2025-04-07 12:14:29
转发有奖 | PostgreSQL 16 PGCM高级认证课程直播班招生中!
墨天轮小教习
152次阅读
2025-04-14 15:58:34
墨天轮PostgreSQL认证证书快递已发(2025年3月批)
墨天轮小教习
131次阅读
2025-04-03 11:43:25
SQL 优化之 OR 子句改写
xiongcc
95次阅读
2025-04-21 00:08:06
融合Redis缓存的PostgreSQL高可用架构
梧桐
90次阅读
2025-04-08 06:35:40
PostgreSQL拓展PGQ实现解析
chirpyli
87次阅读
2025-04-07 11:23:17
Mysql/Oracle/Postgresql快速批量生成百万级测试数据sql
hongg
75次阅读
2025-04-07 15:32:54