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.2017
和 monthEnd=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: 给定起始日期,按月份统计两个日期间每个月份的工作日(非周六周天)的天数,谢谢