简体   繁体   中英

Oracle SQL “complex” group by query optimization

I have an Oracle Report (10g) where i created several graphs.

Now i use two statements like the following in this report. I feel like i had to use two sub-selects in order to get all information the way i want it. But the report now uses 7min to generate and i'm wondering if there's anyway to optimize this query

SELECT quantity ,
  commodity ,
  TO_CHAR(quantity,'9999999990.000') string_quantity
FROM
  (SELECT SUM(quantity) quantity ,
    commodity
  FROM
    (SELECT vtr.quant_p quantity,
      DECODE(vtr.commo_num,'CU','CU,MS,PB','MS','CU,MS,PB','PB','CU,MS,PB',vtr.commo_num) commodity
    FROM v_transactions_postp vtr
    WHERE vtr.compa_num = :P_COMPA_NUM
    AND vtr.customer    = :P_CUSTOMER
    AND vtr.POSTPERIOD BETWEEN :P_PP_START AND :P_PP_END
    )
  GROUP BY commodity
  )
ORDER BY quantity DESC

First, you don't need all the subqueries. And CASE is preferable to DECODE() , especially in this case where it simplifies the code:

SELECT SUM(vtr.quant_p) as quantity,  
       (CASE WHEN vtr.commo_num IN ('CU', 'MS', 'PB') THEN 'CU,MS,PB'
             ELSE vtr.commo_num
        END) as commodity
       TO_CHAR(SUM(vtr.quant_p),'9999999990.000') as string_quantity
FROM v_transactions_postp vtr
WHERE vtr.compa_num = :P_COMPA_NUM AND
      vtr.customer    = :P_CUSTOMER AND
      vtr.POSTPERIOD BETWEEN :P_PP_START AND :P_PP_END
GROUP BY (CASE WHEN vtr.commo_num IN ('CU', 'MS', 'PB') THEN 'CU,MS,PB'
               ELSE vtr.commo_num
          END)
ORDER BY SUM(vtr.quant_p) DESC

Then, for performance, you want an index on v_transactions_postp(compa_num, customer, postperiod) . However, I suspect that the "v_" means "view". That can make the query harder to optimize. You would need the appropriate index on the underlying tables -- or to expand the view in the query.

Try below query:

SELECT sum(vtr.quant_p) quantity,
 (CASE WHEN vtr.commo_num IN ('CU','MS','PB') THEN 'CU,MS,PB' ELSE vtr.commo_num) commodity,
 TO_CHAR(sum(vtr.quant_p), '9999999990.000') string_quantity
 FROM v_transactions_postp vtr
   WHERE vtr.compa_num = :P_COMPA_NUM
     AND vtr.customer = :P_CUSTOMER
     AND vtr.POSTPERIOD BETWEEN :P_PP_START AND :P_PP_END
     GROUP BY commodity
     ORDER BY quantity DESC;

I would suggest you avoid using TO_CHAR in query just to format it in decimal format. You can get quantity and then add formation logic in your code, say in JAVA or PHP.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM