假设我有一张表,如下所示:

--------------------------------------------------
| Type       | Incident ID     | Date of incident|
--------------------------------------------------
| A          | 1               | 2022-02-12      |
| A          | 2               | 2022-02-14      |
| A          | 3               | 2022-02-14      |
| A          | 4               | 2022-02-14      |
| A          | 5               | 2022-02-16      |
| A          | 6               | 2022-02-17      |
| A          | 7               | 2022-02-19      |
| A          | 8               | 2022-02-19      |
| A          | 7               | 2022-02-19      |
| A          | 8               | 2022-02-19      |

 ...          ...               ...             

| B          | 1               | 2022-02-12      |
| B          | 2               | 2022-02-12      |
| B          | 3               | 2022-02-13      |

 ...          ...               ...             

--------------------------------------------------

这是不同类型事件的列表.每个事件都有类型、ID和发生日期.这只是帮助理解我的目标的一个例子.

我想要的是-对于给定的范围,例如5天-这些事件的滚动总和将成为的最大值:

所以我会从前5天内的所有元素开始,并累积出现的次数:6.

2022-02-12 - 2022-02-17:    6

通过开始将窗口滚动一天,第一天的所有元素将从总和中删除,在本例中为-1,并且不会添加第二天的元素.下一个值将是5.

2022-02-13 - 2022-02-18:    5

6>5.因此,6天仍然是5天窗口内事件的最大发生次数.

在完整的时间范围内继续.

这并不是很难实现,但对于数百万个元素,我将如何以非常有效的方式做到这一点?简而言之:我想创建一个固定日期范围(例如5天)的移动窗口,计算此窗口的所有出现次数,并给出任何窗口达到的最大值.

顺便说一句,我正在使用SQLALCHEMY,但我也会对纯SQL感兴趣.

合适的测试集如下所示:

test_data_small = {'Id': [1, 2, 3, 4, 5,
                                6, 7, 8, 9, 10,
                                0, 1, 2, 3],
                   'Type': ['A', 'A', 'A', 'A',
                               'A', 'A', 'A', 'A',
                               'A', 'A', 'B', 'B',
                               'B', 'B'],
                   'Date': [
                       '2022-02-12', '2022-02-14',
                       '2022-02-14', '2022-02-14',
                       '2022-02-16', '2022-02-17',
                       '2022-02-19', '2022-02-19',
                       '2022-02-19', '2022-02-19',
                       '2022-02-16', '2022-02-12',
                       '2022-02-12', '2022-02-13']
                   }

我正在通过SQLALCHEMIY连接到一个表,如下所示:

incidents = select(
            incidents.c.type,
            incidents.c.id,
            incidents.c.date
        ).subquery()

result = self.connection.execute(incidents).fetchall()

在纯SQL中有可能实现吗?也许我应该用Pandas 来装一扇滚动窗?

推荐答案

正如 comments 中已经提到的,这个问题应该在SQL年内得到解决.特别是,它可以用普通的SQL来解决.请注意,因此您只需要使用一个join:您可以在窗口大小所跨越的日期范围和类型上使用join您的表,然后计算相应的条目.

使用您提供的测试数据会产生以下结果.

select
t.id, t.type, t.date, count(*) as num_inc_next_5_days
from tbl as t
    inner join tbl i
            on t.date >= dateadd(day,-5,i.date)
               and t.date <= i.date
               and t.type = i.type
group by t.id, t.type, t.date
order by t.type, t.id, t.date

|----|------|------------|---------------------|
| id | type | date       | num_inc_next_5_days |
|----|------|------------|---------------------|
| 1  | A    | 2022-02-12 | 6                   |
| 2  | A    | 2022-02-14 | 9                   |
| 3  | A    | 2022-02-14 | 9                   |
| 4  | A    | 2022-02-14 | 9                   |
| 5  | A    | 2022-02-16 | 6                   |
| 6  | A    | 2022-02-17 | 5                   |
| 7  | A    | 2022-02-19 | 4                   |
| 8  | A    | 2022-02-19 | 4                   |
| 9  | A    | 2022-02-19 | 4                   |
| 10 | A    | 2022-02-19 | 4                   |
| 0  | B    | 2022-02-16 | 1                   |
| 1  | B    | 2022-02-12 | 4                   |
| 2  | B    | 2022-02-12 | 4                   |
| 3  | B    | 2022-02-13 | 2                   |

最后一列显示future 五天内的事件数量,包括当前日期.如果想要获得这些事件的最大值,只需将查询括在cte内并取最大值:

with cte as (
...
)
select max(...) 
from cte

使用的数据:

create table tbl (
    id int,
    type varchar(1),
    date date
)

insert into tbl values
(1, 'A', '2022-02-12'),
(2, 'A', '2022-02-14'),
(3, 'A', '2022-02-14'),
(4, 'A', '2022-02-14'),
(5, 'A', '2022-02-16'),
(6, 'A', '2022-02-17'),
(7, 'A', '2022-02-19'),
(8, 'A', '2022-02-19'),
(9, 'A', '2022-02-19'),
(10, 'A', '2022-02-19'),
(0, 'B', '2022-02-16'),
(1, 'B', '2022-02-12'),
(2, 'B', '2022-02-12'),
(3, 'B', '2022-02-13');

Python相关问答推荐

Python中两个矩阵的自定义Hadamard风格产物

Python如何让代码在一个程序中工作而不在其他程序中工作

如何知道标志是否由用户传递或具有默认值?

从 struct 类型创建MultiPolygon对象,并使用Polars列出[list[f64]列

如何使用bs 4从元素中提取文本

请从Python访问kivy子部件的功能需要帮助

实现的差异取决于计算出的表达是直接返回还是首先存储在变量中然后返回

Image Font生成带有条形码Code 128的条形码时出现枕头错误OSErsor:无法打开资源

如何根据日期和时间将状态更新为已过期或活动?

在Google Colab中设置Llama-2出现问题-加载判断点碎片时Cell-run失败

将数据框架与导入的Excel文件一起使用

如何在python xsModel库中定义一个可选[December]字段,以产生受约束的SON模式

梯度下降:简化要素集的运行时间比原始要素集长

如何使Matplotlib标题以图形为中心,而图例框则以图形为中心

如何指定列数据类型

如何使regex代码只适用于空的目标单元格

以逻辑方式获取自己的pyproject.toml依赖项

使用__json__的 pyramid 在客户端返回意外格式

当单元测试失败时,是否有一个惯例会抛出许多类似的错误消息?

使用嵌套对象字段的Qdrant过滤