2011-12-30 5 views
3

잠재적으로 1000 개의 레코드가 포함될 수있는보기를 설정하려고합니다. 필드 중 일부는 정확히 동일한 데이터를 반환하는 하위 쿼리가 필요합니다. 때마다 그것을 실행하는 대신보기 내에서 한 번 쿼리 할 수 ​​있는지 궁금 해서요.보기에서 Oracle SQL 재사용 하위 쿼리

PARENT_PK    OUTPUT_VAL_1   OUTPUT_VAL_2   
---------------------- ---------------------- ---------------------- 
1      1      2      
2                  

그래서, 위의 쿼리에서, 나는 다음과 같은 쿼리를 실행하려면 :

DROP VIEW MYVIEW; 
DROP TABLE MYTABLE; 
DROP TABLE MYTABLE_PARENT; 

-- TABLES FOR VIEW 
CREATE TABLE MYTABLE_PARENT (PRIMARY_KEY NUMBER PRIMARY KEY); 
CREATE TABLE MYTABLE (PRIMARY_KEY NUMBER, MYVAL VARCHAR(255), PARENT_PRIMARY_KEY NUMBER); 
INSERT INTO MYTABLE_PARENT VALUES (1); 
INSERT INTO MYTABLE_PARENT VALUES (2); 
INSERT INTO MYTABLE VALUES (1, 'MYVAL1-1', 1); 
INSERT INTO MYTABLE VALUES (2, 'MYVAL1-2', 1); 
INSERT INTO MYTABLE VALUES (3, 'MYVAL2-1', 2); 

-- VIEW 
CREATE OR REPLACE FORCE VIEW MYVIEW AS 
    SELECT CS.PRIMARY_KEY AS PARENT_PK, 

    -- THE BELOW STATEMENTS REUSE THE SAME INNER SUBQUERY, IF THE 
    -- VIEW CONTAINS 1000 ROWS, THE INNER SUBQUERY WILL BE EXECUTED 
    -- 1000 TIMES, RETURNING THE SAME DATA EACH TIME. 
    (SELECT PRIMARY_KEY FROM MYTABLE WHERE MYVAL = 'MYVAL1-1' AND 
    PARENT_PRIMARY_KEY = (SELECT PRIMARY_KEY FROM MYTABLE_PARENT 
    WHERE PRIMARY_KEY = CS.PRIMARY_KEY)) AS OUTPUT_VAL_1, 

    (SELECT PRIMARY_KEY FROM MYTABLE WHERE MYVAL = 'MYVAL1-2' AND 
    PARENT_PRIMARY_KEY = (SELECT PRIMARY_KEY FROM MYTABLE_PARENT 
    WHERE PRIMARY_KEY = CS.PRIMARY_KEY)) AS OUTPUT_VAL_2 
-- DEFINE CS 
    FROM MYTABLE_PARENT CS; 

SELECT * FROM MYVIEW; 

select 문에서 결과는 다음과 같다 : 아래

는 일부 샘플 테이블/데이터입니다 보기의 각 행마다 한 번만 :

(SELECT PRIMARY_KEY FROM MYTABLE_PARENT WHERE PRIMARY_KEY = CS.PRIMARY_KEY) 

내부 하위 쿼리를 최적화 할 수있는 방법이 있습니까? 보기 내에서?

(SELECT PRIMARY_KEY FROM MYTABLE_PARENT WHERE PRIMARY_KEY = CS.PRIMARY_KEY) 

을하지만 별명 CS도 MYTABLE_PARENT를 가리키는 :

+0

왜 모든 MYTABLE_PARENT WHERE primary_key와 = CS.PRIMARY_KEY' 쿼리에서'SELECT primary_key와 필요합니까? CS.PRIMARY_KEY를 사용하지 않는 이유는 무엇입니까? –

답변

3

:

CREATE OR REPLACE FORCE VIEW MYVIEW AS 
    SELECT CS.PRIMARY_KEY AS PARENT_PK, 
     MAX(DECODE(MT.MYVAL, 'MYVAL1-1',MT.PRIMARY_KEY, TO_NUMBER(NULL)) 
         AS OUTPUT_VAL_1, 
     MAX(DECODE(MT.MYVAL, 'MYVAL1-2',MT.PRIMARY_KEY, TO_NUMBER(NULL)) 
         AS OUTPUT_VAL_2 
    FROM MYTABLE_PARENT CS 
    LEFT JOIN MYTABLE MT ON MT.PARENT_PRIMARY_KEY = CS.PRIMARY_KEY AND 
          MT.MYVAL IN ('MYVAL1-1', 'MYVAL1-2') 
    GROUP BY CS.PRIMARY_KEY 
+0

그건 속임수 였어. 감사! 늦은 답변에 대한 사과 – xchagger

0

하위 쿼리 읽기

MYTABLE_PARENT CS; 

그래서 전체 하위 쿼리가 불필요하고, 당신이 CS.PRIMARY_KEY로 대체 할 수? 지금이 권리를 테스트하지만 뷰의 SELECT 부분이 시도 할 수 아니에요

select cs.primary_key as parent_pk 
,   mt1.primary_key 
,   mt2.primary_key 
from  mytable_parent cs 
join  mytable mt1 
on  mt.parent_primary_key = cs.primary_key 
      and mt1.myval = 'myval1-1' 
join  mytable mt2 
on  mt2.parent_primary_key = cs.primary_key 
      and mt2.myval = 'myval1-2' 
+0

내부 조인은 항상 일치하는 mytable 레코드가 있다고 가정합니다. 원래 뷰와 반드시 일치하는 것은 아닙니다. –

2

: 같은

전체 쿼리

는 다시 작성할 수 있습니다. 적어도 중첩 된 하위 쿼리를 잘라낼 것이라고 생각합니다. MYTABLE 및 mytable_parent 각 시도 단일 액세스에 대한

SELECT CS.PRIMARY_KEY AS PARENT_PK, mv1.PRIMARY_KEY AS OUTPUT_VAL_1, mv2.PRIMARY_KEY AS OUTPUT_VAL_2 
FROM MYTABLE_PARENT CS 
LEFT JOIN MYTABLE mv1 ON mv1.PARENT_PRIMARY_KEY = CS.PRIMARY_KEY 
LEFT JOIN MYTABLE mv2 ON mv2.PARENT_PRIMARY_KEY = CS.PRIMARY_KEY 
WHERE mv1.MYVAL = 'MYVAL1-1' 
AND mv2.MYVAL = 'MYVAL1-2'; 
+0

내부 조인은 항상 일치하는 mytable 레코드가 있다고 가정합니다. 원래 뷰와 반드시 일치하는 것은 아닙니다. –

+0

우수한 점, 편집 됨. – Aaron