Oracle SQL 查询移动平均线

Posted

技术标签:

【中文标题】Oracle SQL 查询移动平均线【英文标题】:Oracle SQL Query on moving average 【发布时间】:2021-06-14 15:30:31 【问题描述】:

有一个数据库包含 30 天内的网站流量。 第一个表包含用户信息,包括用户类型(user,crawler,admin)。 第二个表包含每次访问网站的时间、访问者的 ID、在网站上花费的时间(以秒为单位)。

我需要一个 Oracle SQL 查询来显示 users.user_type = 'user' 在网站上花费的 3 天移动平均时间。

表格:-

用户:-

Id Name User_type
1 Matt user
2 John user
3 Louie Admin

交通:-

user_id visited_on time_spent
1 2019-05-01 15
2 2019-05-02 20
2 2019-05-03 10

预期输出:

visited_on Average_time_spent
2019-05-01 15.0000
2019-05-02 17.5000
2019-05-03 15.0000

【问题讨论】:

【参考方案1】:

如果我理解得很好,下面的 select 语句会为你工作

create table Users (Id, Name, User_type) as (
select 1, 'Matt', 'user' from dual union all
select 2, 'John', 'user' from dual union all
select 3, 'Louie', 'Admin' from dual
)
;

create table Traffic (user_id, visited_on, time_spent) as (
select 1, date '2019-05-01', 15 from dual union all
select 2, date '2019-05-02', 20 from dual union all 
select 2, date '2019-05-03', 10 from dual
)
;

select t.VISITED_ON
, avg(t.TIME_SPENT)over(
    order by t.VISITED_ON
       range between interval '2' day preceding and interval '0' day following
) Average_time_spent
from Users u
join Traffic t on u.Id = t.user_id
where u.User_type = 'user'
;

【讨论】:

@user1402648 这不会生成 3 天移动平均线。【参考方案2】:

您可以使用(如果您希望以每天为中心的 3 天平均值):

SELECT visited_on,
       AVG( time_spent ) OVER (
         ORDER BY visited_on
         RANGE BETWEEN INTERVAL '1' DAY PRECEDING AND INTERVAL '1' DAY FOLLOWING
       ) AS average_time_spent
FROM   traffic t
WHERE  EXISTS (
         SELECT 1
         FROM   users u
         WHERE  u.id = t.user_id
         AND u.user_type = 'user'
       )
ORDER BY visited_on

其中,对于样本数据:

CREATE TABLE users ( Id, Name, User_type ) AS
SELECT 1, 'Matt',   'user' FROM DUAL UNION ALL
SELECT 2, 'John',   'user' FROM DUAL UNION ALL
SELECT 3, 'Louie',  'Admin' FROM DUAL;

CREATE TABLE traffic ( user_id, visited_on, time_spent ) AS
SELECT 1,   DATE '2019-05-01',  15 FROM DUAL UNION ALL
SELECT 2,   DATE '2019-05-02',  20 FROM DUAL UNION ALL
SELECT 2,   DATE '2019-05-03',  10 FROM DUAL;

输出:

VISITED_ON | AVERAGE_TIME_SPENT :--------- | -----------------: 19 年 5 月 1 日 | 17.5 19 年 5 月 2 日 | 15 19 年 5 月 3 日 | 15

如果您希望移动平均线是当天和之前的 2,那么您可以更改范围:

SELECT visited_on,
       AVG( time_spent ) OVER (
         ORDER BY visited_on
         RANGE BETWEEN INTERVAL '2' DAY PRECEDING AND INTERVAL '0' DAY FOLLOWING
       ) AS average_time_spent
FROM   traffic t
WHERE  EXISTS (
         SELECT 1
         FROM   users u
         WHERE  u.id = t.user_id
         AND u.user_type = 'user'
       )
ORDER BY visited_on

哪些输出:

VISITED_ON | AVERAGE_TIME_SPENT :--------- | -----------------: 19 年 5 月 1 日 | 15 19 年 5 月 2 日 | 17.5 19 年 5 月 3 日 | 15

db小提琴here

【讨论】:

以上是关于Oracle SQL 查询移动平均线的主要内容,如果未能解决你的问题,请参考以下文章

SQL 移动平均线

面板数据sql移动平均线

在 SQL Server 2012 中计算移动平均线

大查询移动平均线

使用滞后函数在 SQL 中查找移动平均线

R中的累积和、移动平均线和SQL“分组依据”等价物