这将读取您的表格一次。连接是使用仅包含两个值的辅助表完成的(当然这是在内存中 - 没有 I/O)
with t as(
select '1' a, '4' b, '7' c from dual union all
select '2', '5', '5' from dual union all
select '3', '6', '8' from dual
)
select decode(aux.col,1,t.a,'R'), t.b, t.c
from t
join (select '1' col from dual union all select '2' from dual) aux
on (aux.col='1' or t.b=t.c);
查询不依赖于“1”和“2”。有可能:
select decode(aux.col, 'bla', t.a,'R'), t.b, t.c
from t
join (select 'bla' col from dual union all select 'otherbla' from dual) aux
on (aux.col='bla' or t.b=t.c);
更新:此外,如果 b=c 记录的数量很少,您可以加快创建索引的实际查询:
create index fbi on t (b-c);
然后在您的查询中替换WHERE b = c
为WHERE b - c = 0
UPDATE2只是为了了解如何执行这些查询:
create table t(a varchar2(10), b varchar2(10), c varchar2(10));
insert into t
select mod(dbms_random.random(),1000),
mod(dbms_random.random(),1000),
mod(dbms_random.random(),1000)
from dual
connect by level < 1000000;
exec DBMS_STATS.GATHER_TABLE_STATS('DEV','T');
--1
SELECT a, b, c
FROM t;
---------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | 999K| 11M| 700 (3)|
| 1 | TABLE ACCESS FULL| T | 999K| 11M| 700 (3)|
---------------------------------------------------------------
--2
SELECT a, b, c
FROM t
union all
SELECT 'R',b,c
FROM t
WHERE b = c;
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1009K| 11M| 1426 (53)|
| 1 | UNION-ALL | | | | |
| 2 | TABLE ACCESS FULL| T | 999K| 11M| 700 (3)|
| 3 | TABLE ACCESS FULL| T | 10000 | 97K| 726 (7)|
----------------------------------------------------------------
--3
select decode(aux.col, 'bla', t.a,'R'), t.b, t.c
from t
join (select 'bla' col from dual union all select 'otherbla' from dual) aux
on (aux.col='bla' or t.b=t.c);
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20990 | 368K| 1402 (3)|
| 1 | NESTED LOOPS | | 20990 | 368K| 1402 (3)|
| 2 | VIEW | | 2 | 12 | 4 (0)|
| 3 | UNION-ALL | | | | |
| 4 | FAST DUAL | | 1 | | 2 (0)|
| 5 | FAST DUAL | | 1 | | 2 (0)|
| 6 | TABLE ACCESS FULL| T | 10495 | 122K| 699 (3)|
----------------------------------------------------------------
--if the leading table is dual, can be used an /*+ordered*/ hint
--after select clause
--4
create index fbi on t (b-c);
SELECT a, b, c
FROM t
union all
SELECT 'R',b,c
FROM t
WHERE b - c = 0;
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1009K| 11M| 1384 (51)|
| 1 | UNION-ALL | | | | |
| 2 | TABLE ACCESS FULL | T | 999K| 11M| 700 (3)|
| 3 | TABLE ACCESS BY INDEX ROWID| T | 10000 | 117K| 683 (1)|
| 4 | INDEX RANGE SCAN | FBI | 4000 | | 3 (0)|
--------------------------------------------------------------------------
请记住,Oracle 不知道如何很好地预测或加入 3 中的子句,因此最好强制执行所需的执行路径。您应该测试在 2 和 3 和 4 之间进行选择(后面有索引的成本)。