Question

Assuming i have the following table:

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
;

When i am trying to run the following query:

with tt2 as (
select t.*, 
case when rownum = 1 then 1 when rownum = 3 then 3 else null end rfn 

-- RFN is a example for a complex case which only assigns numbers to rows that is needed. Please don't fix on it

from (select id, first_name, salary from employee) t
)

select  
(select id from tt2 where rfn = 3) w
from dual

It returns me all of ID's that is similar to the one where rfn = 3 ( 2500 rows of 26 )

And here is explain plan

"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)"

--edit--

For instance i have table in WITH:

"ID"    "FIRST_NAME"    "SALARY"        "RFN"
"22"    "Jason"        1236.23           1
"24"    "Jason"        1237.89
"26"    "Jason"        1239.56           3

I want to select Salary of anyone with RFN = 1, giving me single number 1236.23

But i also want in the same query to select Salary of enyone with RFN = 3, giving me single number 1239.56.

And so on.

But. For each of this query it makes FULL_TABLE_SCAN of N rows.

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

Explain table:

('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)');

--edited for more clarification--

Expected result from :

"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

from the ~following statement:

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

without 5 full table scans of 2500 rows

Was it helpful?

Solution

You're asking for all rows, you have to change to:

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)

But why do want this result? The ROWNUM is not deterministic without ORDER BY, it's not guaranteed to have the same order every time. You probablly need to use ROW_NUMBER like:

WITH tt2 AS (SELECT t.*, ROW_NUMBER() OVER (ORDER BY ID) rn)
SELECT salary 
FROM tt2 
WHERE rn IN (1,3)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top