递归地将日期列表分组

Posted

技术标签:

【中文标题】递归地将日期列表分组【英文标题】:Recursively dividing a list of dates into groups 【发布时间】:2020-08-10 15:00:34 【问题描述】:

我有一个如下的开始日期列表 -

start dates sorted in descending order

开始日期始终按降序排列。 我正在寻找可以提供以下输出的 postgresql 查询- start dates with groups

基本上,我试图从给定列表中创建日期组,以便组中的每个日期都在相应组顶部日期的 61 天内。 例如 - 在输出中,

组 1 有前 4 条记录,因为所有 4 个开始日期都在 61 以内 记录天数2. 第 2 组仅包含记录号。 6 因为超过 61 天 远离记录号。 2. 组 3 包含行号。 7 和 8,因为他们超过 61 离记录号还有几天。 6. 但在 61 天之内

附:我是 postgresql 和 *** 的新手。 任何指针都会有所帮助

【问题讨论】:

样本数据最好显示为formatted text。请参阅here,了解有关如何创建漂亮表格的一些提示。 会牢记这一点。感谢您的建议 【参考方案1】:

您的示例数据与您的示例输出不匹配。

您在示例输出中的计算是错误的,因为这是倒数,3 月和 10 月都有 31 天。

要正确递归,您需要使用 dense_rank() 分配行号:

with recursive num as (
  select row_number() over (order by start_date desc) as rn,
         start_date
    from dateslist
),

然后,您创建组并通过在递归时将锚值向前传递来找到差距。由于您拥有start_date 信息,您可以同时计算组内的偏移量:

find_gaps as (
  select rn as anchor, start_date as anchor_date, rn, start_date, 0 as group_offset
    from num 
   where rn = 1
  union all
  select case 
           when f.anchor_date - n.start_date > 61 then n.rn
           else f.anchor
         end,
         case 
           when f.anchor_date - n.start_date > 61 then n.start_date
           else f.anchor_date
         end,
         n.rn, n.start_date, 
         case 
           when f.anchor_date - n.start_date > 61 then n.start_date
           else f.anchor_date
         end - n.start_date
    from find_gaps f
    join num n on n.rn = f.rn + 1
)

最后的查询选择你想要输出的列并应用一个组号。

select start_date, 
       dense_rank() over (order by anchor) as group_number,
       group_offset
  from find_gaps
 order by start_date desc;

Working Fiddle Demo

【讨论】:

感谢您的解决方案。这正是我所需要的 我是递归查询的新手。你能帮忙解释一下吗。我尝试使用以下日期进行测试('09-02-2018 00:00')、('07-05-2021 00:00')、('07-05-2021 00:00')、('07- 06-2021 00:00'), ('07-24-2019 00:00') - 但在输出中获得了两条额外的记录 @AnindyaMukherjea 这种重复是由于2021-07-05 在您的数据中输入了两次。如果将 union all 更改为 union,这将导致递归 CTE 消除重复项。请在此处查看更新的小提琴:db-fiddle.com/f/6opXrtd9muc9RvZCj938NS/2 现在它从输出中删除了一行。输入有 12 行,但输出有 11 行。似乎可以将输出视为字典。保持联合和左外连接似乎可以解决问题 - db-fiddle.com/f/6opXrtd9muc9RvZCj938NS/3 @AnindyaMukherjea 对不起。我给了你一个糟糕的解决方案。保留union all,但在顶部cte num 中,将dense_rank() 更改为row_number()。我会更新 DB-fiddle,但看起来该站点现在无法正常工作。我会在上面更新我的答案。

以上是关于递归地将日期列表分组的主要内容,如果未能解决你的问题,请参考以下文章

从流分组中获取唯一日期列表

按月、年对日期列表进行分组

列表视图按日期分组 Dart

t-sql 从平面日期列表中总结日期范围,按其他列分组

Pandas:以列表形式按列分组的每个日期的频率

在mongodb中按月份和日期分组并显示列表