CanNeverThinkOfaName
Programmer
Hi
I'm trying to count the number of people watching TV at a specific minute in time (well I need to do it for every minute in an entire month!)
My data shows when people started and stopped watching TV- so I need to check for every person when they started watching it and whether they shud be included for watching it at e.g. 01/04/2008 00:01:00.
I do this by checking (per account) the last start watching time- check that next stop watching time - if the stop watching is after the required minute i'm checking for, then include this account.
By the time I've done all this (and the table I'm querying has 1.6 million rows and has indexes), it takes 25 minutes to get the final number for just one minute!
I need to do every minute in a month (every month!!)
Has anyone any suggestions to another approach or another way to make it run faster please?
Anything would really be appreciated!!
Sample data here:
script:
I use toad to run and am using Oracle 10g
Thanks in advance
I'm trying to count the number of people watching TV at a specific minute in time (well I need to do it for every minute in an entire month!)
My data shows when people started and stopped watching TV- so I need to check for every person when they started watching it and whether they shud be included for watching it at e.g. 01/04/2008 00:01:00.
I do this by checking (per account) the last start watching time- check that next stop watching time - if the stop watching is after the required minute i'm checking for, then include this account.
By the time I've done all this (and the table I'm querying has 1.6 million rows and has indexes), it takes 25 minutes to get the final number for just one minute!
I need to do every minute in a month (every month!!)
Has anyone any suggestions to another approach or another way to make it run faster please?
Anything would really be appreciated!!
Sample data here:
Code:
CREATE TABLE x
(
ACCOUNTID VARCHAR2(20 BYTE),
SESSIONID VARCHAR2(200 BYTE),
USAGETIMESTAMP DATE,
ELAPSEDTIME_secs NUMBER,
EVENTNAME VARCHAR2(200 BYTE)
);
insert into x values
('69900107727','5A5A7DA61B3E4FC3D8E913999E94E672',to_date(to_char('31/03/2008 23:57:17'),'dd/mm/yyyy hh24:mi:ss'),'','start watching');
insert into x values
('69900107727','5A5A7DA61B3E4FC3D8E913999E94E672',to_date(to_char('01/04/2008 00:03:17'),'dd/mm/yyyy hh24:mi:ss'),'360','stop watching');
Code:
declare sec integer := 0;
cursor c0
is
select to_date(to_char('01/04/2008 00:00:00'),'dd/mm/yyyy hh24:mi:ss') d
from dual;;
addate date;
begin
for r0 in c0
loop
addate := r0.d;
--dbms_output.put_line('start: '||to_char(sysdate,'dd/mm/yyyy hh24:mi:ss'));
while addate < to_date(to_char('01/05/2008 00:00:00'),'dd/mm/yyyy hh24:mi:ss')
loop
addate := r0.d + sec/1440; --every minute
declare
cursor c1
is
select max(usagetimestamp) maxtimestamp,accountid
from x
where usagetimestamp < addate
and eventname like 'start watching%'
group by accountid;
accno varchar2(15) := null;
noviewers number := 0;
begin
select count(distinct accountid)
into noviewers
from x
where usagetimestamp = addate
and eventname like 'start watching%';
for r1 in c1
loop
accno := r1.accountid;
declare cursor c2 is
select min(usagetimestamp) mintimestamp, accountid
from x
where usagetimestamp >= r1.maxtimestamp
and accountid = accno
and eventname like 'stop watching%'
group by accountid;
begin
for r2 in c2
loop
if r2.mintimestamp >= addate
then
noviewers := noviewers + 1;
end if;
end loop;
end;
end loop;
insert into y (addate, noc4viewers, lastupdated) values (addate, noviewers, sysdate);
commit;
end;
sec := sec+1;
--dbms_output.put_line('end: '||to_char(sysdate,'dd/mm/yyyy hh24:mi:ss'));
end loop;
end loop;
end;
/
Thanks in advance