数据分组10秒钟。 PLSQL

时间:2019-09-30 13:20:41

标签: oracle plsql

有必要在一个小时内找到用户在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秒内没有对数据进行分组,请告诉我我在哪里出错了?谢谢!

3 个答案:

答案 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秒的答案