PostgreSQL,对多行的多个日期列求和

PostgreSQL, summing multiple date columns over multiple rows

让我们假设以下 table:

CREATE TABLE assumption ( datetime_1 TIMESTAMP, datetime_2 TIMESTAMP, datetime_3 TIMESTAMP); 

现在我想知道只要日期在未来,任何行或列的组合中一个月设置的总次数。

现在我有:

  SELECT
    COALESCE(
      SUM(
          COALESCE(
               datetime_1 > NOW() AND EXTRACT(MONTH FROM datetime_1) = 1,
               FALSE
          )::INT,
          COALESCE(
               datetime_2 > NOW() AND EXTRACT(MONTH FROM datetime_2) = 1,
               FALSE
          )::INT,
          COALESCE(
               datetime_3 > NOW() AND EXTRACT(MONTH FROM datetime_3) = 1,
               FALSE
          )::INT
      ), 0) AS january_count,
      .... AS february_count,
      .... AS march_count,
      .... AS etc
    FROM assumption;

这行得通并且 returns 得到了正确的结果,但它相当臃肿而且它 returns 我每个月只有一行和一列。 在现实生活中,这个查询有点复杂,我宁愿得到一个结果,每个月给我一行(这样我就可以在每个月的行中添加更多字段)

有什么我遗漏的吗?有什么办法可以改进吗?

你想要横向连接吗?

select date_trunc('month', d.dt) dt_month, count(*) cnt
from assumption a
cross join lateral (values (datetime_1), (datetime_2), (datetime_3)) d(dt)
where dt > now()
group by date_trunc('month', d.dt)

将日期截断到月份的第一天似乎比提取月份更有用(如果您的数据分布在未来几年,结果会有所不同)。但是,如果您的意思是提取月份,则:

select extract(month from d.dt) dt_month, count(*) cnt
from assumption a
cross join lateral (values (datetime_1), (datetime_2), (datetime_3)) d(dt)
where dt > now()
group by extract(month from d.dt)

最后,如果您希望每个月都有一行,即使是那些没有未来时间戳的月,那么:

select extract(month from d.dt) dt_month, count(*) filter(where d.dt > now()) cnt
from assumption a
cross join lateral (values (datetime_1), (datetime_2), (datetime_3)) d(dt)
group by extract(month from d.dt)