按动态时间段分组

时间:2017-04-06 13:34:22

标签: sql postgresql

对于我的问题,我将尝试创建一个简化的例子 表"顺序":

ID |    date    | client | product | product_limit_period (in months)
1  | 2015-01-01 | Bob    | table   | 1
2  | 2015-01-31 | Bob    | table   | 1
3  | 2015-02-01 | Bob    | table   | 1
4  | 2015-01-01 | Mary   | lamb    | 12
5  | 2015-06-01 | Mary   | lamb    | 12
6  | 2016-01-01 | Mary   | lamb    | 12
7  | 2016-12-31 | Mary   | lamb    | 12

这是结果,我想得到:

client | product | group | count
Bob    | table   | 1     | 2       #ID 1, 2
Bob    | table   | 2     | 1       #ID 3
Mary   | lamb    | 3     | 2       #ID 4, 5
Mary   | lamb    | 4     | 2       #ID 6, 7

每件产品都有限制和限制期限(以月为单位)。我需要能够看到是否有任何客户在一定时期内订购的产品超过其限制允许的数量。 月份的月份可能是1个月或几个月。可能是1个月,12个月,24个月,......直到108个月(9年)。

我觉得我需要使用窗口函数和分组的一些组合。但我还没弄清楚怎么做。

我使用postgres 9.1。如果我还有其他信息,请告诉我。

感谢任何帮助,即使只是指向正确的方向!

修改
澄清分组的工作原理:限制期从第一个订单开始。 Bob的第一个订单是2015-01-01,所以这个时期以2015-01-31结束。 2015-02-01开始第二期。 期间始终从一个月的第一天开始,到一个月的最后一天结束。

1 个答案:

答案 0 :(得分:1)

无需同时使用窗口和组合,只需将case添加到窗口或组中,如下所示:

t=# select
  client
, product
, count(1)
, string_agg(id::text,',')
from so44
group by
  client
, product
, date_trunc(case when product_limit_period = 1 then 'month' else 'year' end,date);
  client  |  product  | count | string_agg
----------+-----------+-------+------------
  Bob     |  table    |     2 | 1,2
  Bob     |  table    |     1 | 3
  Mary    |  lamb     |     2 | 4,5
  Mary    |  lamb     |     2 | 6,7
(4 rows)

<强>样品:

t=# create table so44 (i int,"date" date,client text,product text,product_limit_period int);
CREATE TABLE
t=# copy so44 from stdin delimiter '|';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 1  | 2015-01-01 | Bob    | table   | 1
>> 2  | 2015-01-31 | Bob    | table   | 1
3  | 2015-02-01 | Bob    | table   | 1
4  | 2015-01-01 | Mary   | lamb    | 12
5  | 2015-06-01 | Mary   | lamb    | 12
6  | 2016-01-01 | Mary   | lamb    | 12
7  | 2016-12-31 | Mary   | lamb    | 12>> >> >> >> >>
>> \.
COPY 7