2010-08-04 6 views
0

yesterdays 트랜잭션의 모든 주문 수를 배송 날짜별로 그룹화하려면 orders 테이블을 쿼리해야합니다. 그런 다음 모든 거래에 대한 배송 날짜의 총 주문을 제공하는 추가 열이 있어야합니다. 이 두 번째 열을 추가하면 처리 시간이 기하 급수적으로 증가하여 109 초가되었습니다. 이 SQL을 향상시킬 수있는 방법이 있습니까? 여기서 근본적인 것이 빠졌는지 알고 싶을뿐입니다. TRUNC (ORDER_DATE)와 TRUNC (shipping_date) :Oracle Query Optimization Help - 다중 패스

SELECT t.shipping_date 
     , t.net_orders 
     , count(*) as total_orders 
FROM (
    SELECT s.store_num 
      , s.store_cd 
      , to_char(o.shipping_date, 'MM/DD/YYYY') as shipping_date 
      , COUNT (*) as net_orders 
    FROM order o left 
      join store s 
       on (s.store_num = o.store_num) 
    WHERE TRUNC (o.order_date) = TRUNC (SYSDATE - 1) 
    AND s.store_cd = 'ZZZ' 
    AND o.status in ('A', 'B') 
    GROUP BY s.store_num 
      , s.store_cd 
      , to_char(shipping_date, 'MM/DD/YYYY') 
) t 
LEFT JOIN order o ON 
      (TRUNC (o.shipping_date) = to_date(t.shipping_date, 'MM/DD/YYYY') 
      and o.store_num = t.store_num) 
WHERE o.status in ('A', 'B') 
GROUP BY t.shipping_date, t.net_orders; 

나는 다음과 같은 표현뿐만 아니라이 모든 컬럼에 인덱스를 가지고있다.

+0

'shipping_date'및 'order_date'필드 (내부 쿼리)가있는 테이블을 명확히하십시오. – ThinkJet

+0

귀하의 요청에 따라 위의 SQL을 편집했습니다. 감사. – Bradford

답변

1

내가 다시 쓴 쿼리와 같은 :

SELECT t.shipping_date, 
      t.net_orders, 
      COUNT(*) as total_orders 
    FROM (SELECT s.store_num, 
        s.store_cd, 
        o.status, 
        TRUNC(o.shipping_date) AS shipping_date, 
        COUNT (*) as net_orders 
      FROM STORE s 
      JOIN ORDER o ON o.store_num = s.store_num 
         AND o.status IN ('A', 'B') 
      WHERE s.store_cd = 'ZZZ' 
       AND TRUNC(order_date) = TRUNC (SYSDATE - 1) 
    GROUP BY s.store_num, s.store_cd, TRUNC(shipping_date)) t 
LEFT JOIN ORDER o ON TRUNC(o.shipping_date) = t.shipping_date 
       AND o.store_num = t.store_num 
       AND o.status = t.status 
GROUP BY t.shipping_date, t.net_orders; 

약간의 재 배열,하지만 나중에 다시 날짜로 변환하는 TO_CHAR (shipping_date)을 제거했다. TRUNC(shipping_date)은 동일하며 작업을 간소화합니다.

함수를 사용하여 조건에 가입하면 인덱스가 사용되지 않습니다. JOIN 조건과 일치하는 함수 기반 인덱스를 만들어야합니다.

+0

고마움, OMG 조랑말. 이제이 쿼리는 0.78 초로 반환됩니다. 단지 마지막 join, where 제약 조건을 join 제약 조건의 일부로 바꾸었기 때문에 속도가 빨라 졌는가? – Bradford

+0

@Bradford : 예 - 다른 데이터 유형으로 변환하면 특히 해당 정보에 참여하려는 경우 성능이 크게 저하됩니다. –

3

당신은 같은 출력을 찾고 있다면 : 그것은 여분이 주문 테이블에 다시 가입하고 당신이려고하고 있기 때문에 피할 수 있습니다

SELECT * 
    FROM (
    SELECT TRUNC(o.shipping_date) as shipping_date 
     , COUNT(CASE WHEN TRUNC(o.order_date) = TRUNC(SYSDATE - 1) 
         THEN 1 
         ELSE NULL 
        END) as net_orders -- count does not count NULL values. 
     , COUNT(*) as total_orders 
     FROM order o 
      LEFT JOIN 
      store s 
       on s.store_num = o.store_num 
    WHERE s.store_cd = 'ZZZ' 
     AND o.status in ('A', 'B') 
    GROUP BY TRUNC(o.shipping_date) 
    ) 
WHERE net_orders > 0 -- only shipping dates that had at least one order yesterday 

:

shipping_date  net_orders  total_orders 
01-AUG-2004  14    37 
02-AUG-2004  17    29 
03-AUG-2004  19    43 

방법 단지에 대해 어쨌든 상점의 모든 주문을 만져야 할 때 총 수를 얻는 동안 동시에 조건부 집계를 수행 할 수 있습니다.

+0

그래,하지만 모든 출하 일을 알려주지. 어제의 주문에 대해 발생한 배송 날짜 만 표시하려고합니다. – Bradford

+0

죄송합니다. 나는 그것을 간과했습니다. 어제의 주문을 적어도 한 번만 배송하도록 코드를 업데이트했습니다. –