SQL 聚合到最多 3 个日期范围

SQL aggregation into at most 3 date ranges

我需要在 PostgreSQL 中编写一个查询,以根据最多 3 个范围的日期范围从 table 聚合数据。假设我们有以下 table:

CREATE TABLE Purchases (
    ID int,
    PriceCents int,
    PurchaseDate date
);

我想要的是写一个查询到:

1- 取最早的购买日期和最晚的购买日期并将它们分成 3 个不同的日期间隔

2-汇总在计算的时间范围内发生的所有购买的价格并显示

换句话说,假设我们在 table 中有以下数据:

+----+-------------+---------------+
| id | price_cents | purchase_date |
+----+-------------+---------------+
|  1 |         200 | 2020-01-11    |
|  2 |         300 | 2020-01-14    |
|  3 |         100 | 2020-02-02    |
|  4 |         500 | 2020-03-13    |
|  5 |         200 | 2020-07-01    |
|  6 |         300 | 2020-11-17    |
|  7 |         100 | 2021-01-01    |
|  8 |         500 | 2021-01-02    |
+----+-------------+---------------+

在这种情况下,数据介于 2020-01-112021-01-02 之间 当分成 3 个间隔时,它给我们:

2020-01-112020-05-09

2020-05-092020-09-05

2020-09-052021-01-02

我们希望结果是

+------------+--------------------------+
| total_cost |        date_range        |
+------------+--------------------------+
|       1100 | 2020-01-11 to 2020-05-09 |
|        200 | 2020-06-10 to 2020-09-05 |
|        900 | 2020-09-06 to 2021-01-02 |
+------------+--------------------------+

如果我提前知道日期范围并且可以将日期“硬编码”到查询中,这个问题就会变得微不足道,但我不知道。

如果您想要大小相等的范围,请使用 ntile():

select tile, min(purchase_date), max(purchase_date), sum(price_cents)
from (select p.*,
             ntile(3) over (order by purchase_date) as tile
      from purchases p
     ) p
group by tile;

这不是 100% 令人满意,因为范围可以重叠(同一日期可以在两个范围内)。重点是 bin 内的大小相等。所以,如果你想要宽度 bins,那么你可以使用日期算法:

select ceiling((purchase_date - min_pd) / (max_pd - min_pd)) as tile, sum(price_cents)
from (select p.*,
             min(purchase_date) over () as min_pd,
             max(purchase_date) over () as max_pd
      from purchases p
     ) p
group by tile;