PostgresQL:需要语句帮助
考虑一个具有以下PostgresQL数据库表结构的表(为了演示,在这里进行了精简): 随着时间的推移,表格中会出现许多事件。现在,我们需要一个用于报告的SQL statement,它按时间(例如每小时)聚合值,并对特定类型的值进行平均和计数。因此,报告如下所示:PostgresQL:需要语句帮助,sql,postgresql,Sql,Postgresql,考虑一个具有以下PostgresQL数据库表结构的表(为了演示,在这里进行了精简): 随着时间的推移,表格中会出现许多事件。现在,我们需要一个用于报告的SQL statement,它按时间(例如每小时)聚合值,并对特定类型的值进行平均和计数。因此,报告如下所示: [example report for type="standard"] Time Count Avg 00:00 30 20 01:00 12 24 02:00 9 19
[example report for type="standard"]
Time Count Avg
00:00 30 20
01:00 12 24
02:00 9 19
...
在此之前,这是非常直截了当的,因此上述报告的声明如下:
select extract(hour from time) time, count(1), avg(value)
from reportdata
where type = 'standard'
group by time;
现在是棘手的部分-我需要显示每种类型的报告,其中包含所有类型的总数以及每个时间段中与特定类型相关的百分比。
为此,我需要一个语句,它为每个时间帧和每个可能的类型(可以从包含所有可能类型的单独表中选择)生成一行,然后代码可以从中提取每个类型的报告选项卡,而无需再次从数据库请求。
因此,结果应该是这样的(请注意,在没有找到类型值的时间范围内的“空”行):
这句话是怎么产生的?类似这样的话
select extract(hour from rd.time) time,
at.type,
count(at.value) over (partition by extract(hour from time)) as total,
count(at.value) over (partition by rd.type) as count,
avg(value) over (partition by rd.type) as avg,
from all_types at
left join reportdata rd on at.type = rd.type
group by time, at.type;
(all_type
是“包含所有可能类型的单独表格”)
我在时间戳上使用了date\u trunc
,因为我认为你想要的是将每天的每一小时分开。如果你真的想把一天中的每一个小时加起来,只需返回到你的摘录
更新以匹配注释中的新要求:
这正是我所需要的——非常感谢!但还有一个问题:如果在一个时间范围内没有价值,那么就没有价值线。是否可以轻松地在每个时间范围内(当然是在给定的“从”和“到”中的“到”部分)生成这些内容?这很完美,再一次:非常感谢!如果我可以的话,我会给你超过1票。。。
[example report for all types assuming there are 3 possible types]
Time Type Total Count Percent Avg
00:00 standard 40 30 0.75 20
00:00 special 40 10 0.25 8
00:00 super 40 0 0 0
01:00 standard 12 12 1.0 24
01:00 special 12 0 0 0
01:00 super 12 0 0 0
02:00 standard 9 3 0.33 20
02:00 special 9 0 0 0
02:00 super 9 6 0.67 15
...
select extract(hour from rd.time) time,
at.type,
count(at.value) over (partition by extract(hour from time)) as total,
count(at.value) over (partition by rd.type) as count,
avg(value) over (partition by rd.type) as avg,
from all_types at
left join reportdata rd on at.type = rd.type
group by time, at.type;
select
s.hour as "Time",
s.type as "Type",
s.total as "Total",
coalesce(r.total, 0) as "Count",
round(coalesce(r.total, 0) * 1.0/s.total, 2) as "Percent",
round(coalesce(r.avg, 0), 2) as "Avg"
from (
select
date_trunc('hour', time) as hour,
type,
count(*) as total,
avg(value) as avg
from reportdata
group by hour, type
) r
right outer join (
select
date_trunc('hour', time) as hour,
t.type,
count(*) as total
from reportdata
inner join type t on true
group by hour, t.type
) s on s.hour = r.hour and s.type = r.type
order by s.hour, s.type
;
Time | Type | Total | Count | Percent | Avg
---------------------+----------+-------+-------+---------+-------
2012-04-02 00:00:00 | special | 40 | 10 | 0.25 | 8.00
2012-04-02 00:00:00 | standard | 40 | 30 | 0.75 | 20.00
2012-04-02 00:00:00 | super | 40 | 0 | 0.00 | 0.00
2012-04-02 01:00:00 | special | 12 | 0 | 0.00 | 0.00
2012-04-02 01:00:00 | standard | 12 | 12 | 1.00 | 24.00
2012-04-02 01:00:00 | super | 12 | 0 | 0.00 | 0.00
2012-04-02 02:00:00 | special | 9 | 0 | 0.00 | 0.00
2012-04-02 02:00:00 | standard | 9 | 3 | 0.33 | 20.00
2012-04-02 02:00:00 | super | 9 | 6 | 0.67 | 15.00
(9 rows)
select
s.hour as "Time",
s.type as "Type",
s.total as "Total",
coalesce(r.total, 0) as "Count",
case s.total when 0 then round(0, 2) else
round(coalesce(r.total, 0) * 1.0/s.total, 2)
end as "Percent",
round(coalesce(r.avg, 0), 2) as "Avg"
from (
select
date_trunc('hour', time) as hour,
type,
count(*) as total,
avg(value) as avg
from reportdata
group by hour, type
) r
right outer join (
select
date_trunc('hour', d) as hour,
t.type,
count(r.time) as total
from reportdata r
right outer join (
select d
from generate_series(
(select min(time) from reportdata),
(select max(time) from reportdata),
'1 hour'
) g(d)
) g on date_trunc('hour', g.d) = date_trunc('hour', r.time)
inner join type t on true
group by hour, t.type
) s on s.hour = r.hour and s.type = r.type
order by s.hour, s.type
;
Time | Type | Total | Count | Percent | Avg
---------------------+----------+-------+-------+---------+-------
2012-04-01 22:00:00 | special | 1 | 0 | 0.00 | 0.00
2012-04-01 22:00:00 | standard | 1 | 1 | 1.00 | 10.00
2012-04-01 22:00:00 | super | 1 | 0 | 0.00 | 0.00
2012-04-01 23:00:00 | special | 0 | 0 | 0.00 | 0.00
2012-04-01 23:00:00 | standard | 0 | 0 | 0.00 | 0.00
2012-04-01 23:00:00 | super | 0 | 0 | 0.00 | 0.00
2012-04-02 00:00:00 | special | 40 | 10 | 0.25 | 8.00
2012-04-02 00:00:00 | standard | 40 | 30 | 0.75 | 20.00
2012-04-02 00:00:00 | super | 40 | 0 | 0.00 | 0.00
2012-04-02 01:00:00 | special | 12 | 0 | 0.00 | 0.00
2012-04-02 01:00:00 | standard | 12 | 12 | 1.00 | 24.00
2012-04-02 01:00:00 | super | 12 | 0 | 0.00 | 0.00
2012-04-02 02:00:00 | special | 9 | 0 | 0.00 | 0.00
2012-04-02 02:00:00 | standard | 9 | 3 | 0.33 | 20.00
2012-04-02 02:00:00 | super | 9 | 6 | 0.67 | 15.00
2012-04-02 03:00:00 | special | 0 | 0 | 0.00 | 0.00
2012-04-02 03:00:00 | standard | 0 | 0 | 0.00 | 0.00
2012-04-02 03:00:00 | super | 0 | 0 | 0.00 | 0.00
2012-04-02 04:00:00 | special | 1 | 0 | 0.00 | 0.00
2012-04-02 04:00:00 | standard | 1 | 1 | 1.00 | 10.00
2012-04-02 04:00:00 | super | 1 | 0 | 0.00 | 0.00
(21 rows)