简体   繁体   English

sql脚本使用datepart每小时分组并用0填充空

[英]sql script to group hourly using datepart and fill the empty with 0

This script gives the hourly count of the timestamps in the table.此脚本提供表中时间戳的每小时计数。

SELECT date_trunc('hour', s.fill_instant) h , count(date_trunc('hour', s.fill_instant)) c FROM sms s
left join station s2 on
s.station_id = s2.station_id
where
s2.address like '%arizona%' and s.fill_date between '2021-09-19' and '2021-09-19'
GROUP BY date_trunc('hour', s.fill_instant)
order by date_trunc('hour', s.fill_instant) asc;

in the table like the following在如下表中

2021-09-19 00:00:00 3
2021-09-19 02:00:00 20
2021-09-19 03:00:00 6
2021-09-19 13:00:00 7
2021-09-19 14:00:00 11
2021-09-19 15:00:00 6

How can I insert the Zeros in the non present hours.如何在非当前时间插入零。 so it shows the map of complete 24 hours.所以它显示了完整的24小时地图。 much like this很像这样

2021-09-19 00:00:00 3
2021-09-19 01:00:00 0
2021-09-19 02:00:00 20
2021-09-19 03:00:00 6
2021-09-19 04:00:00 0
2021-09-19 05:00:00 0
2021-09-19 06:00:00 0
2021-09-19 07:00:00 0
2021-09-19 08:00:00 0
2021-09-19 09:00:00 0
2021-09-19 10:00:00 0
2021-09-19 11:00:00 0
2021-09-19 12:00:00 0
2021-09-19 13:00:00 7
2021-09-19 14:00:00 11
2021-09-19 15:00:00 6
2021-09-19 16:00:00 0
2021-09-19 17:00:00 0
2021-09-19 18:00:00 0
2021-09-19 19:00:00 0
2021-09-19 20:00:00 0
2021-09-19 21:00:00 0
2021-09-19 22:00:00 0
2021-09-19 23:00:00 0
2021-09-19 24:00:00 0

Use generate_series to get all hours for the given day as a CTE then left join it with your query:使用generate_series获取给定日期的所有小时数作为 CTE,然后left join其与您的查询结合起来:

WITH hours as (Select * from generate_series('2021-09-19 00:00:00'::timestamp, '2021-09-19 23:59:59'::timestamp, INTERVAL '1 hour') as hr)
SELECT hours.hr, coalesce(qry.c, 0) as c
FROM hours 
LEFT JOIN(SELECT date_trunc('hour', s.fill_instant) h , count(date_trunc('hour', s.fill_instant)) c FROM sms s
left join station s2 on s.station_id = s2.station_id
where
s2.address like '%arizona%' and s.fill_date between '2021-09-19' and '2021-09-19'
GROUP BY date_trunc('hour', s.fill_instant)
order by date_trunc('hour', s.fill_instant) asc) qry on qry.h = hours.hr

A more or less generic pattern for filling gaps in a sequence would be this:填充序列中的空白或多或少的通用模式是这样的:
Use your existing query ( t ) and outer join it with the dense sequence of hours ( ds ).使用您现有的查询 ( t ) 并将其与密集的小时序列 ( ds ) 进行外部连接。 Use coalesce to set null values of tc as 0.使用coalescetc null值设置为0。

with t as 
(
 .. your query here .. 
)
select ds.h, coalesce(t.c, 0) c
from generate_series
(
  timestamp '2021-09-19T00:00:00', 
  timestamp '2021-09-19T24:00:00', 
  interval '1 hour'
) as ds(h)  
left outer join t on t.h = ds.h;

Another way to generate all hours of a day is use a recursive query.另一种生成一天中所有小时的方法是使用递归查询。

Then you have to make a LEFT JOIN between hours subquery and your query, and in those rows that do not match your query ( c column is null), you have to put a zero (I used a CASE statement).然后您必须在hours子查询和您的查询之间进行LEFT JOIN ,并且在那些与您的查询不匹配的行中( c列为空),您必须放置一个零(我使用了CASE语句)。

WITH RECURSIVE hours AS (SELECT '2021-09-19 00:00:00'::timestamp AS hour
                         
                         UNION ALL
                         
                         SELECT hour + interval '1 hour'
                         FROM hours
                         WHERE hour < '2021-09-19 23:00:00')
                         
SELECT hours.hour, CASE WHEN sq.c IS NULL THEN 0 ELSE sq.c END AS c
FROM hours
LEFT JOIN (SELECT date_trunc('hour', s.fill_instant) h, count(date_trunc('hour', s.fill_instant)) c 
           FROM sms s
           LEFT JOIN station s2 ON s.station_id = s2.station_id
           WHERE s2.address like '%arizona%' AND s.fill_date = '2021-09-19'
           GROUP BY date_trunc('hour', s.fill_instant)) AS sq ON hours.hour = sq.h
ORDER BY hours.hour;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM