假设我有下表:
create table Employee
(
ID VARCHAR2(4 BYTE) NOT NULL,
First_Name VARCHAR2(10 BYTE),
Last_Name VARCHAR2(10 BYTE),
Start_Date DATE,
End_Date DATE,
Salary Number(8,2),
City VARCHAR2(10 BYTE),
Description VARCHAR2(15 BYTE)
)
;
insert into employee (
ID, First_Name, Last_Name, Start_Date,
End_Date, Salary, City, Description)
select 21 + (level * 2) - 1,'Jason', 'Martin', to_date('19960725','YYYYMMDD'),
to_date ('20060725','YYYYMMDD'), 1234.56+level/3*5, 'Toronto', 'Programmer'
from dual
connect by level < 2501
;
当我尝试运行以下查询时:
with tt2 as (
select t.*,
case when rownum = 1 then 1 when rownum = 3 then 3 else null end rfn
- RFN是一个复杂案例的示例,它只为需要的行分配数字。请不要修理它
from (select id, first_name, salary from employee) t
)
select
(select id from tt2 where rfn = 3) w
from dual
它返回了我所有的ID,类似于rfn = 3(2500行26)
这是解释计划
"PLAN_TABLE_OUTPUT"
"Plan hash value: 2716438026"
" "
"--------------------------------------------------------------------------------------------------------"
"| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |"
"--------------------------------------------------------------------------------------------------------"
"| 0 | SELECT STATEMENT | | 2500 | | 12 (0)| 00:00:01 |"
"|* 1 | VIEW | | 2500 | 42500 | 4 (0)| 00:00:01 |"
"| 2 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6645_8CDDE2 | 2500 | 60000 | 4 (0)| 00:00:01 |"
"| 3 | TEMP TABLE TRANSFORMATION | | | | | |"
"| 4 | LOAD AS SELECT | SYS_TEMP_0FD9D6645_8CDDE2 | | | | |"
"| 5 | COUNT | | | | | |"
"| 6 | TABLE ACCESS FULL | EMPLOYEE | 2500 | 60000 | 8 (0)| 00:00:01 |"
"| 7 | VIEW | | 2500 | | 4 (0)| 00:00:01 |"
"| 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6645_8CDDE2 | 2500 | 60000 | 4 (0)| 00:00:01 |"
"--------------------------------------------------------------------------------------------------------"
" "
"Predicate Information (identified by operation id):"
"---------------------------------------------------"
" "
" 1 - filter(""RFN""=3)"
" "
"Note"
"-----"
" - dynamic sampling used for this statement (level=2)"
- 编辑 -
例如我在WITH中有表:
"ID" "FIRST_NAME" "SALARY" "RFN" "22" "Jason" 1236.23 1 "24" "Jason" 1237.89 "26" "Jason" 1239.56 3
我想选择RFN = 1的任何人的薪水,给我单号码1236.23
但我也想在同一个查询中选择RFN = 3的enyone的薪水, 给我一个号码1239.56。
等等。
但是。对于每个查询,它都会生成N行的FULL_TABLE_SCAN。
with tt2 as (
select t.*, case when rownum = 1 then 1 when rownum = 3 then 3 else null end rfn
from (select id, first_name, salary from employee) t
)
select
(select salary from tt2 where rfn = 1) w,
(select salary from tt2 where rfn = 3) w
from dual
解释表:
('Plan hash value: 1823688231');
(' ');
('--------------------------------------------------------------------------------------------------------');
('| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |');
('--------------------------------------------------------------------------------------------------------');
('| 0 | SELECT STATEMENT | | 2500 | | 12 (0)| 00:00:01 |');
('|* 1 | VIEW | | 2500 | 40000 | 4 (0)| 00:00:01 |');
('| 2 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6651_8CDDE2 | 2500 | 60000 | 4 (0)| 00:00:01 |');
('|* 3 | VIEW | | 2500 | 40000 | 4 (0)| 00:00:01 |');
('| 4 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6651_8CDDE2 | 2500 | 60000 | 4 (0)| 00:00:01 |');
('| 5 | TEMP TABLE TRANSFORMATION | | | | | |');
('| 6 | LOAD AS SELECT | SYS_TEMP_0FD9D6651_8CDDE2 | | | | |');
('| 7 | COUNT | | | | | |');
('| 8 | TABLE ACCESS FULL | EMPLOYEE | 2500 | 60000 | 8 (0)| 00:00:01 |');
('| 9 | VIEW | | 2500 | | 4 (0)| 00:00:01 |');
('| 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6651_8CDDE2 | 2500 | 60000 | 4 (0)| 00:00:01 |');
('--------------------------------------------------------------------------------------------------------');
(' ');
('Predicate Information (identified by operation id):');
('---------------------------------------------------');
(' ');
(' 1 - filter("RFN"=1)');
(' 3 - filter("RFN"=3)');
(' ');
('Note');
('-----');
(' - dynamic sampling used for this statement (level=2)');
- 经过编辑以获得更多说明 -
预期结果来自:
"ID" "FIRST_NAME" "SALARY" "RFN" "22" "Jason" 1236.23 1 "24" "Jason" 1237.89 "26" "Jason" 1239.56 3 "26" "Jack" 1249.56 6 "26" "Wiki" 119.56 8
salary salary1 salary2 name name2 1236.23 1249.56 119.56 Wiki Jack
来自以下声明:
with tt2 as (
select t.*, case when row_number() over (order by id) = 1 then 1 when row_number() over (order by id) = 3 then 3 else null end rfn
from (select id, first_name, salary from employee) t
)
select
(select salary from tt2 where rfn = 1) salary,
(select salary from tt2 where rfn = 6) salary1,
(select salary from tt2 where rfn = 8) salary2,
(select first_name from tt2 where rfn = 8) name,
(select first_name from tt2 where rfn = 6) name2
from dual
没有2500行的全表扫描
答案 0 :(得分:0)
您要求所有行,您必须更改为:
with tt2 as (
select t.*, case when rownum = 1 then 1 when rownum = 3 then 3 else null end rfn
from (select id, first_name, salary from employee) t
)
select salary from tt2 where rfn in (1,3)
但为什么要这个结果呢?如果没有ORDER BY,ROWNUM不是确定性的,不能保证每次都有相同的顺序。您可能需要使用ROW_NUMBER,如:
WITH tt2 AS (SELECT t.*, ROW_NUMBER() OVER (ORDER BY ID) rn)
SELECT salary
FROM tt2
WHERE rn IN (1,3)