4

何千ものレコードを含む可能性のあるビューを設定しようとしています。一部のフィールドでは、まったく同じデータを返すサブクエリが必要です。毎回実行するのではなく、ビュー内でこれを一度クエリできるかどうか疑問に思っていました。

以下は、いくつかのサンプル テーブル/データです。

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                                                                    

したがって、上記のクエリでは、ビューの各行に対して次のクエリを 1 回だけ実行したいと考えています。

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

ビュー内の内部サブクエリを最適化する方法はありますか?

4

3 に答える 3

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
于 2011-12-30T14:43:06.707 に答える
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';
于 2011-12-30T14:33:34.017 に答える
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'
于 2011-12-30T14:29:27.800 に答える