2016-02-13 78 views
3

我需要在幾個時間間隔內獲得同一時期的平均數。
所以,現在我的查詢看起來很醜,是否有可能使它更好?例如,如果我想獲得7周的數據,我需要複製/粘貼相同的線7次,argh!
另外我有一個關於如何放棄極端值的問題(0,10,15,11-從樣本中刪除0)。從數據庫中選擇幾個時期的平均值

SELECT 
    ROUND((w1 + w2 + w3 + w4)/4) 
FROM (
    SELECT COUNT(*) AS w1 
    FROM a.b 
    WHERE id = 1 AND DATE BETWEEN sysdate - 7 - (1/24/4) AND sysdate - 7), 
    (SELECT COUNT(*) AS w2 
    FROM a.b 
    WHERE 
    id = 1 AND DATE BETWEEN sysdate - 14 - (1/24/4) AND sysdate - 14), 
    (SELECT COUNT(*) as w3 
FROM a.b 
WHERE id = 1 AND DATE BETWEEN sysdate - 21 - (1/24/4) AND sysdate - 21), 
    (SELECT COUNT(*) as w4 
FROM a.b 
WHERE id = 1 AND DATE BETWEEN sysdate - 28 - (1/24/4) AND sysdate - 28); 

如果這很重要,我使用的是Oracle DB。

回答

1

也許嘗試使用GROUP BY。

SELECT AVG(C) FROM (
SELECT SUM(1) AS C 
,to_number(to_char(date,'WW')) as DT FROM a.b 
GROUP BY to_number(to_char(date,'WW'))) 
0
SELECT count(*)/4 
FROM a.b 
WHERE id = 1 
AND (DATE BETWEEN sysdate - 7 - (1/24/4) AND sysdate - 7 
OR DATE BETWEEN sysdate - 14 - (1/24/4) AND sysdate - 14 
OR DATE BETWEEN sysdate - 21 - (1/24/4) AND sysdate - 21 
OR DATE BETWEEN sysdate - 28 - (1/24/4) AND sysdate - 28) 

這工作,因爲你只是總結四項罪名,無論如何。

恐怕我不明白你關於丟棄極端值的第二個問題。

0

設置測試數據:

drop table b; 
create table b(event_id number, event_date date); 

begin 
for i in 1 .. 100000 
loop 
insert into b values(floor(dbms_random.value(1,5)),sysdate - abs(dbms_random.normal)*20); 
end loop; 
commit; 
end; 
/

實施例的查詢:

with time_periods (start_time, end_time, period, tp_id) 
    as 
    (select cast((sysdate - 7*(:start_week) - :time_interval) as date), 
      cast((sysdate - 7*(:start_week)) as date), 
      cast(:start_week as number(3)), 
      cast(1 as number(3)) 
     from dual 
     union all 
     select sysdate - 7*(period+1) - :time_interval, 
      sysdate - 7*(period+1), 
      period + 1, 
      tp_id + 1 
     from time_periods 
     where tp_id < :num_weeks 
     ) 
select avg(event_count) 
    from (
    select tp_id, 
     event_count, 
     stddev(event_count) over() std_dev, 
     avg(event_count) over() average 
    from (select tp.tp_id, 
       count(*) event_count 
      from b 
       join time_periods tp 
        on b.event_date between tp.start_time and tp.end_time 
      where b.event_id = 1 
     group by tp.tp_id) 
     ) 
where event_count between average - std_dev and average + std_dev;