user3438498
user3438498

Reputation: 211

Teradata query need optimization

Is there any other way to write the following statement:

(select coalesce(max(ch.chistdate),to_date('01011900','MMDDYYYY'))
      from mydb.chist ch 
      where ch.cactionid in (1,2) 
        and ch.chistdate < inv.jdate 
       and ch.cid = cbo.cid)     = (select max(ch.chistdate) 
                                                from mydb.chist ch 
                                                where ch.cactionid in (3,4) 
                                                  and ch.chistdate < inv.jdate 
                                                  and ch.cid = cbo.cid)

This statement is part of very big query and is included in the where part This is the only part giving no spool space error. I checked tables used for this they give back results quickly.

Main query is here :

select *
from   (select inv.domainnm
  , count(distinct cbo.cid) as numbo
  , trunc(inv.asdate) as asdate
from mydb.inv inv
                  join mydb.ComittedBO cbo on (inv.domainnm = cbo.domainnm 
                                      and inv.jdate >= cbo.sdate
                                      and coalesce(cbo.edate, to_date('01-JAN-3000','DD-MON-RRRR')) >= inv.jdate
                                      and cbo.cid not in (select cpp.cid 
                                                                 from mydb.cpprices cpp
                                                                 where NOT EXISTS (select 1 from mydb.cpitems cpt where cpp.cid = cpt.cid)
                                                                   and trunc(cpp.sdate) <= current_date
                                                                   and ((to_number(to_char(current_date, 'dd')) = 1
                                                                       and coalesce(trunc(cpp.edate),trunc(current_date+1)) >= add_months(trunc(current_date,'mm'),-1))
                                                                       or coalesce(trunc(cpp.edate),trunc(current_date+1)) >= trunc(current_date,'month'))))

                                                                       where ((NOT EXISTS (select 1
            from mydb.customers cu
            where cu.statusid = 3
              and cu.cid = cbo.cid)
   and NOT EXISTS (select 1 
          from mydb.chist ch 
          where ch.cactionid in (3,4) 
            and ch.chistdate < inv.jdate 
            and ch.cid = cbo.cid))



  or
  ((select coalesce(max(ch.chistdate),to_date('01011900','MMDDYYYY'))
      from mydb.chist ch 
      where ch.cactionid in (1,2) 
        and ch.chistdate < inv.jdate 
       and ch.cid = cbo.cid) in (select max(ch.chistdate) 
                                                from mydb.chist ch 
                                                where ch.cactionid in (3,4) 
                                                  and ch.chistdate < inv.jdate 
                                                  and ch.cid = cbo.cid  )
                                                  )   



                                                  )
group by inv.domainnm,trunc(inv.asdate)) inventory
  left join mydb.ahist ah on (inventory.domainnm = ah.domainnm 
                                  and ah.aaid = 7 

                                    and ah.astatusid in (7,9,14,17,19)
                                  and ah.asdate + interval'1' day >= inventory.asdate
                                  and inventory.asdate + interval'1' day >= ah.asdate)
  left join mydb.auction au on (inventory.domainnm = au.domainnm
                               and au.asdate + interval'1' day >= inventory.asdate
                               and inventory.asdate + interval'1' day >= au.asdate)
  left join sdb.harv hv on (inventory.domainnm = hv.domainnm
                                  and hv.sndate + interval'1' day >= inventory.asdate
                                  and inventory.asdate + interval'1' day >= hv.sndate)
  left join mydb.customers "cs" on ah.cid = "cs".cid
  left join mydb.aresult ar on ah.aid = ar.aid
  left join mydb.cdphist cdph on ar.cdpid = cdph.cdpid
  left join mydb.reg rgr on cdph.rid = rgr.rid
where ((to_number(to_char(current_date, 'dd')) = 1
      and inventory.asdate >= add_months(trunc(current_date,'mm'),-1))
      or inventory.asdate >= trunc(current_date,'month'))
  and inventory.asdate < current_date

Thanks.

Upvotes: 0

Views: 129

Answers (2)

anwaar_hell
anwaar_hell

Reputation: 776

Then probably volatile table will solve your problem. Create a volatile table before your main query like below :-

create volatile table tab1
(
chistdateM  date format 'MMDDYYYY'
)primary index(chistdate)
on commit preserve rows;

      insert into tab1 `enter code here`
      select coalesce(max(ch.chistdate),to_date('01011900','MMDDYYYY')) as chistdate
      from mydb.chist ch  , mydb.ComittedBO cbo
      where ch.cactionid in (1,2) 
      and ch.chistdate < inv.jdate 
      and ch.cid = cbo.cid;

create volatile table tab2
(
chistdateS  date format 'MMDDYYYY'
)primary index(chistdate)
on commit preserve rows;
      insert into tab2
      select max(ch.chistdate) from mydb.chist ch 
      where ch.cactionid in (3,4) 
      and ch.chistdate < inv.jdate 
      and ch.cid = cbo.cid  ; 

And use them in you invertory derived table :-

select * from   (select inv.domainnm, count(distinct cbo.cid) as numbo , trunc(inv.asdate) as asdate
from mydb.inv inv  join mydb.ComittedBO cbo on (inv.domainnm = cbo.domainnm    and inv.jdate >= cbo.sdate
                                      and coalesce(cbo.edate, to_date('01-JAN-3000','DD-MON-RRRR')) >= inv.jdate
                                      and cbo.cid not in (select cpp.cid from mydb.cpprices cpp
                                                                 where NOT EXISTS (select 1 from mydb.cpitems cpt where cpp.cid = cpt.cid)
                                                                   and trunc(cpp.sdate) <= current_date
                                                                   and ((to_number(to_char(current_date, 'dd')) = 1
                                                                       and coalesce(trunc(cpp.edate),trunc(current_date+1)) >= add_months(trunc(current_date,'mm'),-1))
                                                                       or coalesce(trunc(cpp.edate),trunc(current_date+1)) >= trunc(current_date,'month'))))
                                                                       where ((NOT EXISTS (select 1
            from mydb.customers cu
            where cu.statusid = 3
              and cu.cid = cbo.cid)
   and NOT EXISTS (select 1 
          from mydb.chist ch 
          where ch.cactionid in (3,4) 
            and ch.chistdate < inv.jdate 
            and ch.cid = cbo.cid))
  or
  ( Select * from tab1 where  chistdateM in (select chistdateS from tab2)    )   
                                                  )
group by inv.domainnm,trunc(inv.asdate)) inventory
  left join mydb.ahist ah on (inventory.domainnm = ah.domainnm 
                                  and ah.aaid = 7 

                                    and ah.astatusid in (7,9,14,17,19)
                                  and ah.asdate + interval'1' day >= inventory.asdate
                                  and inventory.asdate + interval'1' day >= ah.asdate)
  left join mydb.auction au on (inventory.domainnm = au.domainnm
                               and au.asdate + interval'1' day >= inventory.asdate
                               and inventory.asdate + interval'1' day >= au.asdate)
  left join sdb.harv hv on (inventory.domainnm = hv.domainnm
                                  and hv.sndate + interval'1' day >= inventory.asdate
                                  and inventory.asdate + interval'1' day >= hv.sndate)
  left join mydb.customers "cs" on ah.cid = "cs".cid
  left join mydb.aresult ar on ah.aid = ar.aid
  left join mydb.cdphist cdph on ar.cdpid = cdph.cdpid
  left join mydb.reg rgr on cdph.rid = rgr.rid
where ((to_number(to_char(current_date, 'dd')) = 1
      and inventory.asdate >= add_months(trunc(current_date,'mm'),-1))
      or inventory.asdate >= trunc(current_date,'month'))
  and inventory.asdate < current_date

Please validate your data as per your requirement.

Upvotes: 0

JNevill
JNevill

Reputation: 50209

Just concentrating on your Inventory derived table, I moved the two SELECT statements that were giving you problems from the WHERE clause to to the FROM clause with a LEFT OUTER JOIN.

I also combined them into a single statement that had three fields: The cid for joining to the cbo table, and then two CASE statements for each set of cactionid (1 and 2, 3 and 4). Then, in the WHERE clause I just tested for where the max(chistdate) from each CASE equaled eachother.

SELECT 
    inv.domainnm, 
    count(DISTINCT cbo.cid) AS numbo, 
    trunc(inv.asdate) AS asdate
FROM mydb.inv inv
INNER JOIN mydb.ComittedBO cbo  
    ON (
            inv.domainnm = cbo.domainnm AND 
            inv.jdate >= cbo.sdate AND 
            coalesce(cbo.edate, to_date('01-JAN-3000', 'DD-MON-RRRR')) >= inv.jdate AND 
            cbo.cid NOT IN 
                (
                    SELECT cpp.cid
                    FROM mydb.cpprices cpp
                    WHERE 
                        NOT EXISTS 
                            (
                                SELECT 1
                                FROM mydb.cpitems cpt
                                WHERE cpp.cid = cpt.cid
                            ) AND 
                        trunc(cpp.sdate) <= CURRENT_DATE 
                        AND 
                            (
                                (
                                    to_number(to_char(CURRENT_DATE, 'dd')) = 1 AND 
                                    coalesce(trunc(cpp.edate), trunc(CURRENT_DATE + 1)) >= add_months(trunc(CURRENT_DATE, 'mm'), - 1)
                                )
                                OR coalesce(trunc(cpp.edate), trunc(CURRENT_DATE + 1)) >= trunc(CURRENT_DATE, 'month')
                            )                                   
                )
            )
LEFT OUTER JOIN 
    (
        SELECT 
            ch.cid, 
            max(CASE WHEN ch.cactionid IN (1,2) THEN coalesce(max(ch.chistdate), DATE '1900-01-01')) as chistdate_ai12,
            max(CASE WHEN ch.cactionid IN (3,4) THEN ch.chistdate) as chistdate_ai34
        FROM chist ch
        WHERE ch.chistdate < inv.jdate
        GROUP BY ch.cid
    ) ch ON
    cbo.cid = ch.cid
WHERE (
        (
            NOT EXISTS (
                SELECT 1
                FROM mydb.customers cu
                WHERE cu.statusid = 3 AND cu.cid = cbo.cid
                ) 
            AND NOT EXISTS (
                SELECT 1
                FROM mydb.chist ch
                WHERE ch.cactionid IN (3, 4) AND ch.chistdate < inv.jdate AND ch.cid = cbo.cid
                )
        ) 
        OR ch.chistdate_ai12 = ch.chistdate_ai34
      )
GROUP BY inv.domainnm, trunc(inv.asdate)

I think there are a lot more efficiencies to be gained by working through this query more, but hopefully this will get you the same results (I believe it will, but without seeing your database schema and some sample data, it's tough to rewrite complex stuff like this), and hopefully it will run without jamming up your limited spool space.

Upvotes: 0

Related Questions