2011-12-30 55 views
3

我試圖設置一個可能包含1000條記錄的視圖。某些字段需要返回完全相同數據的子查詢。我想知道是否可以在視圖中查詢一次,而不是每次都運行它。查看內部的Oracle SQL重用子查詢

下面是一些示例表/數據:

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語句的結果如下:

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

所以,在上面的查詢,我想運行下面的查詢只有一次在視圖中的每一行:

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

有沒有什麼辦法可以優化內部的subquer視野內的ies?

+0

爲什麼你需要的'SELECT PRIMARY_KEY FROM MYTABLE_PARENT WHERE PRIMARY_KEY = CS.PRIMARY_KEY'查詢呢?爲什麼不使用CS.PRIMARY_KEY? – 2011-12-30 14:34:57

回答

3

對於單個接入每個MYTABLE和mytable_parent,嘗試:

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 2012-02-02 14:06:09

0

子查詢寫着:

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

但別名CS還指着MYTABLE_PARENT:

MYTABLE_PARENT CS; 

所以整個子查詢是多餘的,你可以用CS.PRIMARY_KEY取代它呢?

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記錄 - 不一定是原始視圖。 – 2011-12-30 14:44:43

2

我不能現在來測試這個權利,但這種嘗試爲您的視圖的SELECT部分​​:

整個查詢關鍵詞,比如可以再被改寫。我在想它至少會剪掉你的嵌套子查詢。

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記錄 - 不一定是原始視圖。 – 2011-12-30 14:44:26

+0

優秀的點,編輯。 – Aaron 2011-12-30 14:51:58