Oracle查询具有特定列平均值的最新行?
Posted
技术标签:
【中文标题】Oracle查询具有特定列平均值的最新行?【英文标题】:Oracle query latest row with average for specific column? 【发布时间】:2015-05-06 05:12:08 【问题描述】:拥有以下数据集。我需要一些关于 sql 语句的帮助,该语句将为我提供基于 PING_DATE
的最新行,具有唯一的 PING_DESTINATION
和 PING_SOURCE
,并为过去 10 分钟内的所有行添加了 AVG
的 PING_AVG
列。
PING_DATE | PACKET_LOSS | PING_MIN | PING_AVG | PING_MAX | PING_SOURCE | PING_DESTINATION
-------------------------------------------------------------------------------------------------------
5/5/2015 12:58:18 PM | 0 | 68 | 68 | 72 | site1 | orange15
5/5/2015 12:58:43 PM | 0 | 68 | 71 | 76 | site1 | orange15
5/5/2015 12:59:11 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 1:09:47 PM | 0 | 68 | 70 | 76 | site1 | pear11
5/5/2015 1:43:59 PM | 0 | 68 | 69 | 72 | site1 | pear11
5/5/2015 1:45:41 PM | 0 | 68 | 69 | 72 | site1 | pear11
5/5/2015 2:03:43 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 3:01:53 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 3:02:05 PM | 0 | 68 | 69 | 72 | site1 | pear11
5/5/2015 3:00:59 PM | 20 | 68 | 68 | 68 | site1 | pear11
5/5/2015 3:01:07 PM | 0 | 68 | 68 | 72 | site1 | pear11
5/5/2015 3:01:14 PM | 0 | 68 | 70 | 72 | site1 | pear11
5/5/2015 12:46:55 PM | 3 | 3 | 3 | 3 | site1 | lemon1
查询结果:
PING_DATE | PACKET_LOSS | PING_MIN | PING_AVG | PING_MAX | PING_SOURCE | PING_DESTINATION | 10minavg
------------------------------------------------------------------------------------------------------------------
5/5/2015 12:58:43 PM | 0 | 68 | 71 | 76 | site1 | orange15 | 71
5/5/2015 3:01:14 PM | 0 | 68 | 70 | 72 | site1 | pear11 | 65
5/5/2015 12:46:55 PM | 3 | 3 | 3 | 3 | site1 | lemon1 | 3
【问题讨论】:
给出示例输出...问题不清楚。最好做一个表格来显示输出应该如何显示 组site1, orange15
没有 71
的 10 分钟平均值,而是 69.5
((68+71)/2 = 69.5
... 还是没有?)
site1, pear11
组的相同问题有 10 分钟平均 (68+68+70+68+69)/5 = 68.6
。那么,您究竟希望您的“最后 10 分钟平均值”如何工作?
【参考方案1】:
对于“过去 10 分钟的平均值”是“每组的最后 10 分钟”,这是您要查找的查询:
with xyz as (
select X.*,
row_number() over (
partition by ping_destination, ping_source
order by ping_date desc
) as latest_row#,
avg(ping_avg) over (
partition by ping_destination, ping_source
order by ping_date asc
range between
interval '10' minute preceding
and current row
) as the_10_min_avg
from ping_table X
)
select *
from xyz
where latest_row# = 1
;
对于“过去 10 分钟平均值”是“从 10 分钟前到现在”,这是您要查找的查询:
with xyz as (
select X.*,
row_number() over (
partition by ping_destination, ping_source
order by ping_date desc
) as latest_row#,
avg(ping_avg) over (
partition by ping_destination, ping_source
) as the_10_min_avg
from ping_table X
where X.ping_date >= systimestamp - interval '10' minute
)
select *
from xyz
where latest_row# = 1
;
【讨论】:
有效,但我得到的行超过 10 分钟。 您希望行距“现在”不超过 10 分钟?? 啊,该死的,你一开始就应该在你的问题中这么说。【参考方案2】:类似这样的:
SELECT DISTINCT ping_source,
first_value(ping_date) over (partition by ping_source order by ping_date desc),
first_value(packet_loss) over (partition by ping_source order by ping_date desc)
-- ...
FROM data
CROSS JOIN
select avg(ping_avg) from data
where (sysdate - ping_date) * 24 * 60 < 10;
【讨论】:
【参考方案3】:这是一个基于问题的直接查询。
根据示例输出进行编辑。从现在开始的最后 10 分钟,在 sn -p "(i.latest_ping - interval '10' minute)" 中使用 systemtimestamp 而不是 i.latest_ping。在该源-目标对的 max_ping_time 的最后 10 分钟内使用 i.latest_ping。
select
o.*,
(select avg(ping_avg) from ping_info a
where a.ping_source = i.ping_source
and a.ping_dest = i.ping_dest
and a.ping_date >= (systemtimestamp - interval '10' minute)
) last_10min_avg
from ping_info o,
(select ping_source, ping_dest, max(ping_date) latest_ping
from ping_info
group by ping_source, ping_dest) i
where o.ping_source = i.ping_source
and o.ping_dest = i.ping_dest
and o.ping_date = i.latest_ping;
【讨论】:
有效,但我得到的行超过 10 分钟。以上是关于Oracle查询具有特定列平均值的最新行?的主要内容,如果未能解决你的问题,请参考以下文章
在执行 Select 查询时,如何忽略 Postgresql 中某列具有特定值的数据行?
使用 plsql 或 javascript 在 oracle apex 20.1 中的交互式网格中获取行仅包含特定列中的特定值