Oracle SQL Self Join advice -


this first question on forum, patient... question efficient way build query on following table:

create table opentrades(     accountnumber   number,     snapshottime    date,     ticket      number,     opentime    date,     tradetype   varchar2(4),     tradesize   number,     tradeitem   char(6),     openprice   number,     tradesl     number,     tradetp     number,     tradeswap   number,     tradeprofit number   );  alter table opentrades add constraint opentrades_pk primary key (accountnumber, snapshottime, ticket) using index tablespace mynnidx;` 

this table populated every 15 minutes, , timestamp of insert saved in snapshottime column. sought query should group records week number (based on snapshottime), , filter records return latest (snapshottime) within same week.

so far, i've tried following:

select myweekno(ot1.snapshottime), max(ot2.snapshottime) opentrades ot1, opentrades ot2 myweekno(ot2.snapshottime)=myweekno(ot1.snapshottime) group myweekno(ot1.snapshottime);. 

( note: myweekno() modified version of to_char(,'iw'). )

however, takes way longer expected (15 minutes less 1500 rows); i'm sure there's better way write this, far, has eluded me. idea?

you don't need self-join @ all. you'll same result just:

select myweekno(ot.snapshottime), max(ot.snapshottime) opentrades ot group myweekno(ot.snapshottime); 

you may find useful add virtual column holding calculated week number, won't have performance impact query, , wouldn't benefit indexing either. no filter you'd need full table scan anyway, unless calculated value , snapshottime indexed, , may not desirable.

your question suggests might want other data latest rows in each grouped week, , have multiple rows per snapshot. might explain self-join approach: you're trying find latest snapshot date in each week , plan join find rows snapshot dates? though may misinterpreting that. if trying though, can use analytic function assign ranking each row based on snapshot date , week number, , filter see ranked first:

select weekno, snapshottime, accountnumber -- , other columns (   select ot.*, myweekno(ot.snapshottime) weekno,     rank() on (partition myweekno(ot.snapshottime)       order ot.snapshottime desc) ranking   opentrades ot ) ranking = 1 order weekno, accountnumber, ticket; 

sql fiddle demo.


if 'snapshot' can contain dates spanning period of, say, 10 minutes, use alternative analytic approach records in latest load:

select weekno, snapshottime, accountnumber, ticket (   select ot.*, myweekno(ot.snapshottime) weekno,     max(snapshottime) on (partition myweekno(ot.snapshottime)) latestend   opentrades ot ) snapshottime > latestend - interval '10' minute  , snapshottime <= latestend order weekno, accountnumber, ticket; 

here latestend inner query last snapshottime week, , filter ignores isn't between time , ten minutes before it.

sql fiddle showing 5 records recent load selected, , preceding load skipped.


Comments

Popular posts from this blog

database - VFP Grid + SQL server 2008 - grid not showing correctly -

jquery - Set jPicker field to empty value -

.htaccess - htaccess convert request to clean url and add slash at the end of the url -