我有一个看起来像这样的postgres表:
proposal_id | nih_budget_start | nih_budget_end | nsf_start_date | nsf_end_date | award_amount
proposal_A | 03/01/2000 | 12/31/2000 | | | 10,000
proposal_B | | | 08/01/2005 | 07/31/2009 | 5,000,000
proposal_C | 06/27/2012 | 11/17/2013 | | | 420,000
日期包含date
数据类型。
我想创建一个视图,告诉我每年提案的资金来源,以及平均奖金额是多少。因此,视图可能看起来像这样(选项1):
proposal_id | start_year | end_year | average_award
proposal_A | 2000 | 2000 | 10,000
proposal_B | 2005 | 2009 | 1,000,000
proposal_C | 2012 | 2013 | 210,000
或 - 甚至更好 - 这(选项2):
proposal_id | year | award
proposal_A | 2000 | 10,000
proposal_B | 2005 | 1,000,000
proposal_B | 2006 | 1,000,000
proposal_B | 2007 | 1,000,000
proposal_B | 2008 | 1,000,000
proposal_B | 2009 | 1,000,000
proposal_C | 2012 | 210,000
proposal_C | 2023 | 210,000
此外,将奖励金额按比例分配给部分年度资金可能会很好,但这并非完全必要。
基于下面建议的答案,我目前正在这样做,这似乎按预期工作,以获得上面的选项1:
CREATE VIEW award_per_year AS
select t1.proposal_id,t1.START_DATE,t1.END_DATE,
(t1.adjusted_award_amount/((t1.END_DATE - t1.START_DATE) + 1.)) avg_award
from
(select t2.proposal_id,
(extract(year from START_DATE)) START_DATE,
(extract(year from END_DATE)) END_DATE,
t2.adjusted_award_amount from
(select proposal_id,
case when nih_budget_start is not NULL then nih_budget_start else nsf_start_date end start_date,
case when nih_budget_end is not NULL then nih_budget_end else nsf_end_date end end_date,
adjusted_award_amount from proposal)t2)t1
答案 0 :(得分:2)
选项1:使用COALESCE
SELECT proposal_id, start_year, end_year
, award_amount/((end_year - start_year) + 1.0) AS avg_award
FROM (
SELECT proposal_id
, extract(year FROM COALESCE(nih_budget_start, nsf_start_date))::int AS start_year
, extract(year FROM COALESCE(nih_budget_end, nsf_end_date))::int AS end_year
, award_amount
FROM proposal
) sub;
选项2:使用generate_series()
SELECT proposal_id
, generate_series(start_year, end_year) AS year
, award_amount/((end_year - start_year) + 1.0) AS avg_award
FROM (
SELECT proposal_id
, extract(year FROM COALESCE(nih_budget_start, nsf_start_date))::int AS start_year
, extract(year FROM COALESCE(nih_budget_end, nsf_end_date))::int AS end_year
, award_amount
FROM proposal
) sub;
答案 1 :(得分:1)
根据您的澄清,您最好获得如下列表:
proposal_ID | years_funded | average_award
proposal_A | 2000 | 10,000
proposal_B | 2005 | 1,000,000
proposal_B | 2006 | 1,000,000
proposal_B | 2007 | 1,000,000
proposal_B | 2008 | 1,000,000
proposal_B | 2009 | 1,000,000
proposal_C | 2012 | 210,000
proposal_C | 2013 | 210,000
在前端,您可以使用此列表显示年度明智的提案资金。请确认。
根据您的输入,这里有一个查询,可以实现您想要的第一个输出结果集:
SELECT proposal_id,
TO_CHAR(COALESCE(nih_budget_start, nsf_start_date),'YYYY') AS start_year,
TO_CHAR(COALESCE(nih_budget_end, nsf_end_date),'YYYY') AS end_year,
award_amount/(TO_CHAR(COALESCE(nih_budget_end, nsf_end_date),'YYYY')::INT - TO_CHAR(COALESCE(nih_budget_start, nsf_start_date),'YYYY')::INT+1) AS average_award
FROM Proposals
以下查询可以使用递归CTE实现第二个结果集:
WITH RECURSIVE dates AS
(
SELECT proposal_id,nih_budget_start,nsf_start_date,nih_budget_end,nsf_end_date, TO_CHAR(COALESCE(nih_budget_start, nsf_start_date),'YYYY')::INT AS Dt,
award_amount/(TO_CHAR(COALESCE(nih_budget_end, nsf_end_date),'YYYY')::INT - TO_CHAR(COALESCE(nih_budget_start, nsf_start_date),'YYYY')::INT+1) AS average_award
FROM proposals
UNION ALL
SELECT proposal_id,nih_budget_start,nsf_start_date,nih_budget_end,nsf_end_date, d1.dt + 1, average_award FROM dates d1
WHERE d1.dt < TO_CHAR(COALESCE(nih_budget_end, nsf_end_date),'YYYY')::INT
)
SELECT proposal_id, dt AS year, average_award FROM dates d ORDER BY proposal_id,dt
请参阅SQLFiddle
上的代码答案 2 :(得分:1)
尝试此查询:
select t1.proposal_ID,t1.START_DATE,t1.END_DATE,
DIV(t1.award,(t1.END_DATE - t1.START_DATE + 1))award
from
(select t2.proposal_ID,
(substr(t2.START_DATE,7,4)::integer) START_DATE,
(substr(t2.END_DATE,7,4)::integer) END_DATE,
t2.award from
(select proposal_ID,
case when length(start_date1) = 10 then start_date1 else start_date2 end start_date,
case when length(end_date1) = 10 then end_date1 else end_date2 end end_date,
award from table1)t2)t1;