sql - 使用计算值枚举两个日期之间的年份

标签 sql database postgresql view generate-series

我有一个看起来像这样的 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 数据类型。

我想创建一个 View ,告诉我该提案每年获得资助,以及平均奖励金额是多少。因此, View 可能看起来像这样(选项 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

最佳答案

选项 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;

-> SQLfiddle

关于sql - 使用计算值枚举两个日期之间的年份,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21988487/

相关文章:

node.js - 如何使用 express 保留数据库的一个实例

javascript - NodeJS Postgres 错误 getaddrinfo ENOTFOUND

postgresql - sql : how to select a row with a true value from a column of boolean values after the HAVING clause

database - 如何建立适用于所有 Mac 的 Java DB 连接,以便其 JAR 能够在 Windows 10 上建立连接?

sql - SQLite3 在 Node.js 中有准备好的语句吗?

mysql - 从与前一行有较大值差距的行中获取 ID - MySQL

sql - 如何使用两个表执行更新

mysql - Mysql UUID_SHORT() 是否与 UUID() 相当

sql - 在 select 和 where 子句中使用存储过程返回值,而不必调用它两次?

c# - 服务器的全局文化在不同服务器上不同时的 DateTime 问题