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;
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
Post a Comment