2015-01-23 5 views
-1

다음의 SQL을 좀 더 효율적으로 작성하고 싶습니다 (오라클 분석 함수를 사용하지만 효과가있는 모든 다시 작성이 가능할 수 있습니다). 현재 작동하는 SQL, 그냥 실행하는 데 시간이 걸릴 : - : 표에전체 SQL 쿼리 다시 작성

CREATE TABLE ITEM_REF 
(
    DEPT_ID VARCHAR2(5 BYTE) NOT NULL 
, ID VARCHAR2(11 BYTE) NOT NULL 
, ID_TYPE VARCHAR2(1 BYTE) NOT NULL 
, ITEM_CHARGE VARCHAR2(15 BYTE) NOT NULL 
, ITEM_PAYMENT VARCHAR2(15 BYTE) NOT NULL 
, ITEM_DATE DATE NOT NULL 
, REF_AMT NUMBER(14, 2) NOT NULL 
) 

삽입 :

INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000001', '000000000000002', '11/JUN/09', '1550') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000003', '000000000000004', '23/OCT/09', '3100') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000005', '000000000000007', '02/AUG/10', '3500') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000008', '000000000000010', '15/DEC/10', '3500') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000003', '000000000000004', '14/APR/11', '0') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000012', '000000000000014', '14/APR/11', '3100') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000021', '000000000000022', '13/JUL/11', '3500') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000016', '000000000000018', '03/JUN/11', '1550') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000016', '000000000000018', '22/JUN/11', '0') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000017', '000000000000019', '22/JUN/11', '1550') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000005', '000000000000007', '13/JUL/11', '0') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000021', '000000000000022', '19/SEP/11', '0') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000021', '000000000000024', '19/SEP/11', '3500') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000023', '000000000000025', '21/NOV/11', '1550') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000027', '000000000000030', '03/NOV/14', '384') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000028', '000000000000030', '03/NOV/14', '247.8') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0004', 'O', '000000000000026', '000000000000029', '27/OCT/14', '2465') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0002', 'O', '000000000000001', '000000000000004', '07/JUL/10', '88.4') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0002', 'O', '000000000000001', '000000000000004', '13/JUL/10', '88.4') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0002', 'O', '000000000000001', '000000000000006', '17/AUG/10', '353.6') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0002', 'O', '000000000000001', '000000000000004', '21/AUG/10', '88.4') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0002', 'O', '000000000000001', '000000000000006', '21/AUG/10', '87.6') 
INSERT INTO ITEM_REF VALUES ('POLLD', '0002', 'O', '000000000000001', '000000000000006', '25/AUG/10', '353.6') 

현재 누적 합계 SQL :

SELECT A.DEPT_ID, A.ID, A.ID_TYPE, A.ITEM_CHARGE, A.ITEM_DATE 
, NVL((SELECT SUM(B.REF_AMT) FROM ITEM_REF B 
     WHERE B.DEPT_ID  = A.DEPT_ID 
      AND B.ID   = A.ID 
      AND B.ID_TYPE  = A.ID_TYPE 
      AND B.ITEM_CHARGE = A.ITEM_CHARGE 
      AND B.ITEM_DATE = 
      (SELECT MAX(B2.ITEM_DATE) 
       FROM ITEM_REF B2 
       WHERE B2.DEPT_ID  = B.DEPT_ID 
        AND B2.ID   = B.ID 
        AND B2.ID_TYPE  = B.ID_TYPE 
        AND B2.ITEM_CHARGE = B.ITEM_CHARGE 
        AND B2.ITEM_PAYMENT = B.ITEM_PAYMENT 
        AND B2.ITEM_DATE <= A.ITEM_DATE) 
     ), 0) 
FROM ITEM_REF A GROUP BY A.DEPT_ID, A.ID, A.ID_TYPE, A.ITEM_CHARGE, A.ITEM_DATE 

표 만들기

다음과 같이 Oracle 분석 함수를 사용하려고 시도했습니다. -

SELECT A.DEPT_ID 
, A.ID 
, A.ID_TYPE 
, A.ITEM_CHARGE 
, A.ITEM_DATE 
, (SELECT SUM(B.REF_AMT) 
    FROM ITEM_REF B 
    WHERE B.DEPT_ID =A.DEPT_ID 
    AND B.ID   =A.ID 
    AND B.ID_TYPE  =A.ID_TYPE 
    AND B.ITEM_CHARGE =A.ITEM_CHARGE 
    AND B.ITEM_DATE = 
     (SELECT C.ITEM_DATE 
     FROM 
      (SELECT D.ITEM_DATE 
        , ROW_NUMBER() OVER (PARTITION BY D.DEPT_ID, D.ID, D.ID_TYPE, D.ITEM_CHARGE, D.ITEM_PAYMENT ORDER BY D.ITEM_DATE DESC) RN 
       FROM ITEM_REF D 
       WHERE D.ITEM_DATE <= A.ITEM_DATE 
       ) C 
     WHERE C.RN =1 
     ) 
    ) 
FROM ITEM_REF A 

내부 SQL 여기에 테이블 ITEM_REF의 A. 내 접근 방식을 참조 할 수 없기 때문에 휴식이 코드를 A.ITEM_DATE하는 기준은 주 SQL 테이블의 예에서 주어진 날짜를 기준으로 최대 ITEM_DATE를 반환하는 오라클 분석 기능을 사용하는 것입니다 ITEM_REF A. 감사

+0

스택 오버플로에 오신 것을 환영합니다! 이 사이트는 작성한 소프트웨어로 인해 발생하는 문제에 대해 질문하고 답변을 얻을 수있는 사이트이지만 "나에게 숙제를 할 것"또는 "나를 위해 내 업무를 수행"사이트가 아닙니다. 질문을 할 때 작성한 코드 **와 얻는 특정 오류 ** 또는 프로그램에서 생성 한 결과와 예상 한 결과에 대한 설명을 포함시켜야합니다. 그것 없이는 우리가 당신을 도울 수있는 것이별로 없습니다. 질문을 편집하여 수행 한 작업을 보여주고 코드에 어떤 문제가 있는지 알려주십시오. 다시, Stack Overflow에 오신 것을 환영합니다! –

+1

빠른 "create table #ITEM_REF"및 몇 가지 구문을 사용하여 샘플 데이터를 삽입 할 수 있습니다. –

+1

에 대해 실행하거나 실행해야 할 항목이 있습니다. B_ED가 B2로되어 있거나 B_ED가 무엇입니까? –

답변

0

업데이트 대답 데이터 시작 부분에 그룹화 및 row_number로 행을 정렬과

쿼리. 나는 당신이 그룹화 한 후에 훨씬 적은 행이 있다면 더 좋을 것이라고 생각합니다. 75 만 줄에 대해 시도해 보니 새 버전이 더 빨랐습니다.

어쩌면 내가 틀렸다,하지만 현재 실행중인 쿼리가 마지막으로 단순 합계를 반환 :하지만 난 당신의 쿼리를 선호 , 그것은

다음
with ds as (select dept_id, id, id_type, item_charge, item_date, item_payment, sum(ref_amt) ref_amt 
    from item_ref 
    group by dept_id, id, id_type, item_charge, item_date, item_payment), 
dsp as (
    select ds1.dept_id, ds1.id, ds1.id_type, ds1.item_charge, ds1.item_date, ds2.ref_amt, 
     row_number() over (partition by ds2.dept_id, ds2.id, ds2.id_type, ds2.item_charge, 
     ds2.item_payment, ds1.item_date order by ds2.item_date desc) rn 
    from ds ds1 join ds ds2 on ds2.dept_id=ds1.dept_id and ds2.id=ds1.id and ds2.id_type=ds1.id_type 
     and ds2.item_charge=ds1.item_charge and ds2.item_date<=ds1.item_date) 
select dept_id, id, id_type, item_charge, item_date, sum(ref_amt) 
    from dsp where rn=1 
    group by dept_id, id, id_type, item_charge, item_date 

이 아닌 실제 지금 이전의 대답이다 ;-) 더 읽기입니다 같은 열 amt. 샘플 레코드를 추가하여 결과를 세 번 확인했는데 아무런 차이가 없습니다.

select dept_id, id, id_type, item_charge, item_date, 
    sum(ref_amt) amt, 
    sum(sum(ref_amt)) over (partition by dept_id, id, id_type, item_charge 
     order by item_date) amt_aggr 
    from item_ref a 
    group by dept_id, id, id_type, item_charge, item_date 

합계를 늘리려면 amt_aggr과 같은 것을 사용할 수 있습니다.

+0

맞습니다. 초기 샘플 데이터가 주어지면 코드가 잘 작동합니다. 업데이트 된 샘플 데이터로 시도하십시오. ITEM_PAYMENT는 REF_AMT의 합계에 영향을줍니다. 또한 귀하의 회신에 감사드립니다. – everythingisawesome

+0

업데이트 된 더 나은 예제를 사용해 주셔서 감사합니다.하지만 지금까지 성공하지 못했습니다. 힌트 - 복합 인덱스를 추가하려고하면 (DEPT_ID, ID, ID_TYPE, ITEM_CHARGE, ITEM_DATE), 실행 속도가 훨씬 빨라질 것입니다. –