postgres按相似的日期将数据分组

7dl7o3gd  于 2021-08-09  发布在  Java
关注(0)|答案(1)|浏览(325)

我有一个table要叫 data_rows 这样地:

create table if not exists data_rows
(
    id                integer  not null,
    constraint data_rows_to_group
        primary key (id),
    date              date     not null,
    group_id          int, 
    --more fields that are not relevant
);

当我按日期排序行时,如果与前一行的日期差异大于7天(可以是另一个时间跨度,但让它保持在7天),我希望这些行具有新的组id,因此按日期排序时具有相同组id的所有行的日期差异小于等于7天。例如:

id      date        group id
1      12.01.2019   0
2      15.01.2019   0
3      21.01.2019   0
4      05.02.2019   1
5      08.02.2019   1
6      20.02.2019   2
7      30.02.2019   3
8      30.02.2019   3

(特别是1和3在同一组中,虽然它们的差异大于7,但在组中,后面两行没有差异大于7)
我知道如何用python或c#或类似的语言以过程化的方式实现这一点。但是如果我能在postgresql服务器上做这件事,那将是非常有用的,因为它有大量的数据,它也会使它保持一个单一的故障点,这将是一个巨大的学习经验。
下面是我在c语言中的实现方法,这样你就知道我想要什么了:

using System;
using System.Collections.Generic;
using System.Linq;

class DataRows
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public int GroupId { get; set; }
}

class GroupMarking
{
    public DataRows[] RowsWithGroupIds(IEnumerable<DataRows> relevantDataRows, TimeSpan betweenSpan)
    {
        var currentGroupId = 0;
        var rows = relevantDataRows.OrderBy(p => p.Date).ToArray();
        rows[0].GroupId = currentGroupId;
        for (var i = 1; i < rows.Length; i++)
        {
            if (rows[i].Date -
                rows[i - 1].Date >= betweenSpan)
            {
                currentGroupId++;
            }
            rows[i].GroupId = currentGroupId;
        }
        return rows;
    }
}

这在postgresql中可能吗?我知道postgres里有循环。我更喜欢没有循环的解决方案,但如果没有循环是不可能的,它们是可以的。如何在不使用过程语言的情况下在group\u id列中创建id?

sqougxex

sqougxex1#

这是一个缺口和孤岛问题,可以通过将差异大于7天的信息转换为一个标志,然后对该标志求和来解决:

select id, "date", sum(flag) over (order by "date") as group_id
from (
  select id, "date", 
         ("date" - lag("date", 1, "date") over (order by "date") > 7)::int as flag
  from data_rows
) t
order by "date"

表达式 "date" - lag("date", 1, "date") over (order by "date") 计算“当前”行和上一行之间的日期差。如果大于7天,则检查此值,布尔值转换为整数(0,1),以便可以对其使用外部运行和。
在线示例
(我将失效日期2019-02-30替换为2019-02-28)

相关问题