有必要在一个小时内找到用户在10秒内处理的消息的平均数量。 PLSQL 有以下几列:订户,日期(“ dd.mm.yyyy hh.mm.ss”)和消息,它们是相关的(每条消息都有自己的时间以及处理消息的订户)。
想法是这样的:
SELECT subscriber, HH24, AVG(CNT) FROM (
SELECT subscriber,
trunc(date, 'HH24') HH24,
trunc(date - INTERVAL '10' SECOND) SS,
count(messages) CNT
FROM tables
where date IS NOT NULL
GROUP BY subscriber,
trunc(date, 'HH24'),
trunc(date - INTERVAL '10' SECOND)
order by subscriber)
GROUP BY subscriber, HH24
预期结果:
subscriber HH24 CNT
subscriber 1 01.01.01 21:00:00 8,88
subscriber 1 01.01.01 22:00:00 7,88
subscriber 2 01.01.01 21:00:00 6,66
subscriber 3 01.01.01 22:00:00 5,54
我的查询产生如下内容:
subscriber HH24 CNT
subscriber 1 01.01.01 21:00:00 400
subscriber 1 01.01.01 22:00:00 500
subscriber 2 01.01.01 21:00:00 300
subscriber 3 01.01.01 22:00:00 500
我的请求很可能在10秒内没有对数据进行分组,请告诉我我在哪里出错了?谢谢!
答案 0 :(得分:0)
请尝试以下操作:
select subscriber, ss, count(сообщения) cnt from (
select subscriber,
trunc(date) + (floor((date-trunc(date))*24*60*60/10)*10)/24/60/60 as ss,
сообщения
from tables
where date is not null)
group by subscriber, ss;
我最好解释一下这个大表情:
(date-trunc(date))*24*60*60 -- Time expressed as number of seconds since midnight (T1)
(floor(T1/10)*10) -- ... rounded down to nearest 10 seconds (T2)
T2/24/60/60 -- ... converted to fraction of a day (T3)
trunc(date)+T3 -- ... added back on to date
答案 1 :(得分:0)
不清楚您要寻找什么。对于此类任务,我使用以下通用函数:
CREATE OR REPLACE FUNCTION MakeInterval(ts IN TIMESTAMP, roundInterval IN INTERVAL DAY TO SECOND) RETURN TIMESTAMP DETERMINISTIC IS
denom INTEGER;
BEGIN
IF roundInterval >= INTERVAL '1' HOUR THEN
denom := EXTRACT(HOUR FROM roundInterval);
IF MOD(24, denom) <> 0 THEN
RAISE VALUE_ERROR;
END IF;
RETURN TRUNC(ts) + TRUNC(EXTRACT(HOUR FROM ts) / denom) * denom * INTERVAL '1' HOUR;
ELSIF roundInterval >= INTERVAL '1' MINUTE THEN
denom := EXTRACT(MINUTE FROM roundInterval);
IF MOD(60, denom) <> 0 THEN
RAISE VALUE_ERROR;
END IF;
RETURN TRUNC(ts, 'hh') + TRUNC(EXTRACT(MINUTE FROM ts) / denom) * denom * INTERVAL '1' MINUTE;
ELSE
denom := EXTRACT(SECOND FROM roundInterval);
IF MOD(60, denom) <> 0 THEN
RAISE VALUE_ERROR;
END IF;
RETURN TRUNC(ts, 'mi') + TRUNC(EXTRACT(SECOND FROM ts) / denom) * denom * INTERVAL '1' SECOND;
END IF;
END MakeInterval;
然后您可以像MakeInterval("date", INTERVAL '10' SECOND)
一样简单地使用它
但是,也许您正在寻找windowing_clause,例如
AVG(CNT) OVER (PARTITION BY subscriber ORDER BY "date" RANGE BETWEEN CURRENT_ROW AND INTERVAL '10' SECOND FOLLOWING)
答案 2 :(得分:0)
我讲得不好,但是问题解决如下:
SELECT subscriber, HH24, AVG(cnt / 3600) * 100 / 10 cnt
AVG-平均值,CNT / 3600-除以每小时的秒数,* 100-转换为百分比,/ 10-我们得到10秒的答案