当另一个表中的条目发生更改时,我有一个包含单个条目的历史表。我需要执行一个查询,为每个时间段生成最近条目的sum()或count()。
这是我的表结构的相关位:
CREATE TABLE opportunity_history (
"id" BIGSERIAL PRIMARY KEY,
"opportunity_id" TEXT NOT NULL,
"employee_external_id" TEXT NOT NULL,
"item_date" TIMESTAMP NOT NULL,
"amount" NUMERIC(18,2) NOT NULL DEFAULT 0
);
例如,如果我在1月份创建了一个机会,并在2月份更新了两次,我想在1月份计算一次,而在2月份只计算一次。
我所拥有的其他类似查询(不涉及历史记录 - 只是单个数据点)通过在单个查询中加入generate_series()而正常工作。我希望能够实现类似的东西。以下是使用generate_series的示例:
SELECT Periods.day, sum(amount) as value
FROM (
SELECT generate_series('2012-01-01', '2013-01-01', '1 month'::interval)::date AS day
) as Periods LEFT JOIN opportunity ON (
employee_external_id='...'
AND close_date >= Periods.day
AND close_date < Periods.day
)
GROUP BY 1
ORDER BY 1
然而,这对于opportunity_history并不起作用,因为如果在同一个月内列出一个项目两次就会出现重复。
我真的很难过这个。我试过通过WITH RECURSIVE来做这件事,似乎没有任何东西适合我。
修改
示例数据(跳过id列并使用日期而不是时间戳):
'foo', 'user1', 2013-01-01, 100
'bar', 'user1', 2013-01-02, 50
'foo', 'user1', 2013-01-12, 100
'bar', 'user1', 2013-01-13, 55
'foo', 'user1', 2013-01-23, 100
'foo', 'user1', 2013-02-04, 100
'foo', 'user1', 2013-02-15, 100
'bar', 'user1', 2013-03-01, 55
总和我想要的:
2013-01 155 (foo on 2013-01-23 and bar on 2013-01-13)
2013-02 100 (foo on 2013-02-15)
2013-03 55 (bar on 2013-03-01)
或计数:
2013-01 2
2013-02 1
2013-03 1
另请注意,我很高兴使用&#34;扩展&#34; SQL,如CTE或WITH RECURSIVE或窗口函数(如果需要)。如果我可以在单个查询中执行此操作,我宁愿避免使用Pg / plsql函数中的循环。
答案 0 :(得分:1)
select item_month, count(*), sum(amount)
from (
select opportunity_id,
item_date,
amount,
to_char(item_date, 'yyyy-mm') as item_month,
row_number() over (partition by opportunity_id, to_char(item_date, 'yyyy-mm') order by item_date desc) as rn
from opportunity_history
) t
where rn = 1
group by item_month
order by 1;
SQLFiddle示例:http://sqlfiddle.com/#!15/c4152/1
答案 1 :(得分:0)
这是你需要的吗?
select
opportunity_id,
extract(year from item_date) as year,
extract(month from item_date) as month,
count(*),
sum(amount)
from opportunity_history
group by opportunity_id, year, month
order by opportunity_id, year, month
如果没有,请解释您需要的其他内容/为何错误。