我在波斯格雷斯有一张像贝劳尔一样的桌子

start_at end_at
17/1/2023 15/3/2023

我想像贝洛一样把它分了

start_at end_at
17/1/2023 31/1/2023
01/2/2023 28/2/2023
1/3/2023 15/3/2023

我试过生成一系列的postgres,但无法生成欲望行.请有人帮我

推荐答案

Recommended Solution(h/t: Prosenjit Chongder):

使用101函数的解决方案更加紧凑.

SELECT TO_CHAR(GREATEST(y, c.start_at), 'DD/MM/YYYY') AS start_at,
       TO_CHAR(LEAST(y + INTERVAL '1 month' - INTERVAL '1 day', c.end_at), 'DD/MM/YYYY') AS end_at
FROM date_ranges c, 
     generate_series(date_trunc('month', c.start_at::timestamp), date_trunc('month', c.end_at::timestamp), INTERVAL '1 month') y
ORDER BY GREATEST(y, c.start_at), LEAST(y + INTERVAL '1 month' - INTERVAL '1 day', c.end_at);

Fiddle


较旧的解决方案:

你需要一个递归Common table expression来达到你的目的.

WITH RECURSIVE date_split(start_at, end_at, current_start, current_end) AS (
  SELECT start_at, end_at,
         start_at, LEAST(end_at, (date_trunc('MONTH', start_at) + INTERVAL '1 MONTH' - INTERVAL '1 day')::DATE)
  FROM date_ranges
  WHERE start_at <= end_at
  UNION ALL
  SELECT start_at, end_at,
         (current_end + INTERVAL '1 day')::DATE,
         LEAST(end_at, (date_trunc('MONTH', current_end + INTERVAL '1 day') + INTERVAL '1 MONTH' - INTERVAL '1 day')::DATE)
  FROM date_split
  WHERE current_end < end_at
)
SELECT TO_CHAR(current_start, 'DD/MM/YYYY') AS start_at, TO_CHAR(current_end, 'DD/MM/YYYY') AS end_at
FROM date_split
ORDER BY current_start;

输出:

start_at    end_at
17/01/2023  31/01/2023
01/02/2023  28/02/2023
01/03/2023  15/03/2023

DBFiddle

Database相关问答推荐

如何限制报表中返回的行数?

MongoDB 中的 OVER PARTITION 类似功能

如何将 Scylla DB 中的计数器列重置为零?

如何从 PostgreSQL 触发器发送邮箱?

我应该为 Realm 中的每个实体定义主键吗?

基于邮政编码的纬度和经度

如何连接到 MDF 数据库文件?

如何将视图的所有权限授予任意用户

将实体框架中的字符串列映射到枚举

如何使用 SQL 命令文件创建 SQLite3 数据库文件?

数据库表中的索引有什么缺点?

将 Android Room 数据库与 Firebase 实时数据库相关联

我什么时候应该考虑使用内存数据库,需要注意什么问题?

如何从 Django 中的 sql 模式生成数据模型?

CouchDB、MongoDB 和 Redis 中的哪个数据库适合从 Node.js 开始?

从原始物理文件中恢复 postgreSQL 数据库

ManyToOneRel 和 ForeignKey 的区别?

查询以查找列的 nᵗʰ 最大值

Windows phone 7 的本地 Sql 数据库支持

包含 8000 万条记录并添加索引的表需要超过 18 小时(或永远)!怎么办?