Postgresql 统计月份活跃天数

Posted

技术标签:

【中文标题】Postgresql 统计月份活跃天数【英文标题】:Postgres sql count number of days active in month 【发布时间】:2017-06-05 07:25:35 【问题描述】:

我有一张这样的桌子:

meterId | startDate  | endDate  |location
meter01 | 2017-05-01 |2017-05-16| locA
meter02 | 2017-05-01 |9999-12-31| locB
meter03 | 2017-01-01 |9999-12-31| locA
meter04 | 2017-01-01 |9999-12-31| locB

我需要返回某个位置在给定月份中的活动天数。查询需要返回: (假设 5 月有 31 天)

location |  Month  |  days  | 
locA     |  May-17 |    47  |
locB     |  May-17 |    62  |

到目前为止我尝试过的是这样的:(请注意,我正在加入另一个不是最佳的表,并在此处显示)

SELECT count(distinct(read_date)) AS days, location from t where EXTRACT(MONTH FROM read_date) = 5 and EXTRACT(YEAR FROM read_date) = 2017

有点接近。然而,它有重复的位置。我还需要上述格式的日期。

@StanislavL 的新编辑

    select SUM(sub.intervalEnd - sub.intervalStart +1) as days,
     location
from (select 
    location,
    case when effective_start_date> '2017-05-01' then effective_start_date else '2017-05-01' end as intervalStart,
    case when effective_end_date< '2017-05-31' then effective_end_date else '2017-05-31' end as intervalEnd
from my_table

where (effective_start_date<='2017-05-01' and effective_end_date>='2017-05-01')
   OR (effective_start_date<='2017-05-31' and effective_end_date>='2017-05-31'))sub
  group by location

【问题讨论】:

5 月 17 日的 locA 计数是从哪里得到的?根据您的数据,计数看起来不正确。 @Sumit, 16 + 31 = 47 @Sumit 是的,第一个仪表只活跃了 16 天,而其余的仪表则整个月都活跃。 表格中的读取日期在哪里? 我稍微修改了您的查询,请试试这个。 SELECT count(distinct(read_date)) AS days, to_char(read_date, 'Month')||'-'|| to_char(read_date,'YY')as Month, location from t where EXTRACT(MONTH FROM read_date) = 5 and EXTRACT(YEAR FROM read_date) = 2017 GROUP BY Location, read_date 【参考方案1】:

您应该首先引入一个选择来检索所需的间隔。

select 
    location,
    case when startDate> :monthBegin then startDate else :monthBegin end as intervalStart,
    case when endDate< :monthEnd then endDate else :monthEnd end as intervalEnd,
from the_table t
where (startDate<=:monthBegin and endDate>:monthBegin)
   OR (startDate<:monthEnd and endDate>=:monthEnd)

monthBegin=01.05.2017monthEnd=31.05.2015 的位置

然后将选择放在另一个的 FROM 部分

select SUM(sub.intervalEnd - sub.intervalStart) as days,
       sub.location
from (subselect) sub

需要对区间差求和的地方

【讨论】:

嗨,斯坦,我已经尝试过您的查询,它运行但没有结果。你能检查一下我做了什么吗?我已将其添加到原始问题的底部。谢谢 从内部查询中删除 group by - 子 group by location, effective_start_date, effective_end_date/ 理想情况下创建 SQL fiddle。很难一味地分辨出什么是错的。首先执行内部查询以确保它返回所需的时间间隔/ 在某些情况下您还可以在case when 中使用'''。为什么? 我想我的查询现在可以工作了。但是,出于某种原因,我不得不在顶部添加 +1 以获得正确的数量 - 大概你的建议计算了排除或其他东西之间的天数。我只是想知道这样做是否有任何影响,例如它可以将空值拉入表中还是什么?我已经在我的问题中编辑了查询以显示。但除此之外似乎工作...... 我认为+1 是正确的。如果我们从2017-05-01 中减去2017-05-01,则结果为0,但在您的情况下应该为1。我认为最终结果查询很好。如果有效,请接受正确的答案。【参考方案2】:

对于任何感兴趣的人,这是最终的工作示例

select location,  subItem1, item2, SUM(sub.intervalEnd - sub.intervalStart +1) as days

from (select 
    location, item1,item2,
    case when effective_start_date> '2017-05-01' then effective_start_date else '2017-05-01' end as intervalStart,
    case when effective_end_date< '2017-05-31' then effective_end_date else '2017-05-31' end as intervalEnd,
    case when item1 =  'APPLE' then item1 else 'ORANGE' end as subItem1
from myTable

where (effective_start_date<='2017-05-01' and effective_end_date>='2017-05-01')
   OR (effective_start_date<='2017-05-31' and effective_end_date>='2017-05-31')
group by item1, item2, location, effective_start_date, effective_end_date
   )sub
  group by location, subItem1, item2

那里有一些额外的字段和一个“案例”查询(项目 1、项目 2)以满足我自己的需要,这可能会有所帮助。

【讨论】:

以上是关于Postgresql 统计月份活跃天数的主要内容,如果未能解决你的问题,请参考以下文章

oracle: 给定起始日期,按月份统计两个日期间每个月份的工作日(非周六周天)的天数,谢谢

如何根据日期获取月份的天数?

在 PostgreSQL 中,选择会计年度月份格式作为日期列

计算年月天数

计算年月天数

PostgreSQL TO_CHAR() 删除月份字段的填充