Oracle查询具有特定列平均值的最新行?

Posted

技术标签:

【中文标题】Oracle查询具有特定列平均值的最新行?【英文标题】:Oracle query latest row with average for specific column? 【发布时间】:2015-05-06 05:12:08 【问题描述】:

拥有以下数据集。我需要一些关于 sql 语句的帮助,该语句将为我提供基于 PING_DATE 的最新行,具有唯一的 PING_DESTINATIONPING_SOURCE,并为过去 10 分钟内的所有行添加了 AVGPING_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 中某列具有特定值的数据行?

SQL查询从数据中获取最新价格?

查找特定字符串格式的 Oracle 查询

如何仅获取特定行的列均值?

使用 plsql 或 javascript 在 oracle apex 20.1 中的交互式网格中获取行仅包含特定列中的特定值

当前行和上一行之间具有特定值的窗口函数