我正在尝试设置一个可能包含1000条记录的视图。某些字段需要子查询,这些子查询返回完全相同的数据。我想知道我是否可以在视图中查询一次,而不是每次都运行它。
以下是一些示例表/数据:
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)
有没有办法在视图中优化内部子查询?
答案 0 :(得分: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
答案 1 :(得分: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';
答案 2 :(得分: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'