按日期进行有条件的分组

lus*_*eer 4 sql postgresql aggregate

我有点麻烦这个问题.

我有两个表itemsstocks

items
id | name 
1  | item_1    
2  | item_2    

stocks
id | item_id | quantity | expired_on
1  |    1    |    5     |  2015-11-12
2  |    1    |    5     |  2015-11-13
3  |    2    |    5     |  2015-11-12
4  |    2    |    5     |  2015-11-14
Run Code Online (Sandbox Code Playgroud)

我希望能够检索按日期分组的大表,并且对于每个日期,按item_id分组,并显示未过期的数量总和.

result
date        | item_id | unexpired 
2015-11-11  |    1    |    10     
2015-11-11  |    2    |    10     
2015-11-12  |    1    |    5     
2015-11-12  |    2    |    5     
2015-11-13  |    1    |    0     
2015-11-13  |    2    |    5     
2015-11-14  |    1    |    0     
2015-11-14  |    2    |    0
Run Code Online (Sandbox Code Playgroud)

如果只有一天我能够检索到结果

SELECT 
  items.id, SUM(stocks.quantity) as unexpired
FROM 
  items LEFT OUTER JOIN stocks 
  ON items.id = stocks.item_id
WHERE 
  stocks.expired_on > '2015-11-11'
GROUP BY
  items.id, stocks.quantity
Run Code Online (Sandbox Code Playgroud)

我四处搜索,找到了一个名为DatePart的东西,但它似乎不像我需要的东西.

Clo*_*eto 5

使用来自booleanto 的方便的强制转换integer,产生0,1或null,仅对未过期的求和

select
    to_char(d, 'YYYY-MM-DD') as date,
    item_id, 
    sum(quantity * (expired_on > d)::int) as unexpired
from
    stocks
    cross join 
    generate_series(
        '2015-11-11'::date, '2015-11-14', '1 day'
    ) d(d)
group by 1, 2
order by 1, 2
;
    date    | item_id | unexpired 
------------+---------+-----------
 2015-11-11 |       1 |        10
 2015-11-11 |       2 |        10
 2015-11-12 |       1 |         5
 2015-11-12 |       2 |         5
 2015-11-13 |       1 |         0
 2015-11-13 |       2 |         5
 2015-11-14 |       1 |         0
 2015-11-14 |       2 |         0
Run Code Online (Sandbox Code Playgroud)

cross joingenerate_series定范围内提供所有日期.

上面使用的数据:

create table stocks (
    id int,
    item_id int,
    quantity int,
    expired_on date
);
insert into stocks (id,item_id,quantity,expired_on) values
(1,1,5,'2015-11-12'),
(2,1,5,'2015-11-13'),
(3,2,5,'2015-11-12'),
(4,2,5,'2015-11-14');
Run Code Online (Sandbox Code Playgroud)