Запрос

serg4321
Дата: 26.02.2007 18:47:40
Добрый всем вечер!

Хочу спросить у Вас, можно ли для данной задачи построить более оптимальный запрос?

Есть таблица1 и есть таблица2 с такой же структурой.
create table m(id number, val varchar2(1));
create table t(id number, val varchar2(1));


insert into m values(1, 'X');
insert into m values(2, 'X');
insert into m values(3, 'X');

insert into t values(3, 'Y');
insert into t values(4, 'Y');
insert into t values(5, 'Y');

Мне нужно выбрать все поля из таблицы 1, но с одним условием: если PK таблицы1 есть в таблице2, то строка должна быть выбрана из таблицы2 (для данного PK). У меня пока реализовано таким образом:
select s.id, nvl(t.val, m.val) value
from 
(select id from m 
 union
 select id from t) s 
left join m on s.id= m.id 
left join t on s.id= t.id
order by s.id;

drop table m;
drop table t;

        ID VALUE
---------- -----
         1 X
         2 X
         3 Y
         4 Y
         5 Y

Но мне не нравится план выполнения (по 2 full scan на каждую таблицу).

--------------------------------------------------------------------------------
Plan hash value: 2596495759
--------------------------------------------------------------------------------
| Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |     6 |   258 |    16  (25)| 00:00:01 |
|   1 |  SORT ORDER BY          |      |     6 |   258 |    16  (25)| 00:00:01 |
|*  2 |   HASH JOIN OUTER       |      |     6 |   258 |    15  (20)| 00:00:01 |
|*  3 |    HASH JOIN OUTER      |      |     6 |   168 |    12  (25)| 00:00:01 |
|   4 |     VIEW                |      |     6 |    78 |     8  (25)| 00:00:01 |
|   5 |      SORT UNIQUE        |      |     6 |    78 |     8  (63)| 00:00:01 |
|   6 |       UNION-ALL         |      |       |       |            |          |
|   7 |        TABLE ACCESS FULL| M    |     3 |    39 |     3   (0)| 00:00:01 |
|   8 |        TABLE ACCESS FULL| T    |     3 |    39 |     3   (0)| 00:00:01 |
|   9 |     TABLE ACCESS FULL   | M    |     3 |    45 |     3   (0)| 00:00:01 |
|  10 |    TABLE ACCESS FULL    | T    |     3 |    45 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Заранее спасибо за ответы.
orawish
Дата: 26.02.2007 18:55:56
select m.id, nvl(t.val, m.val) value
from m ,t
where t.id (+) = m.id
order by m.id;
Ну и (вообще) план исследовать смысл имеет на более представительных данных
serg4321
Дата: 26.02.2007 19:04:19
Сорри, немного не до конца описал задачу. Вообщем можно ли добиться такого результата:
 select s.id, t.val, m.val
from 
(select id from m 
 union
 select id from t) s 
left join m on s.id= m.id 
left join t on s.id= t.id
order by s.id;

       ID  VAL VAL
---------- --- -----
         1     X
         2     X
         3 Y   X
         4 Y   
         5 Y   
только без двойных full scan'ов исходных таблиц?
orawish
Дата: 26.02.2007 19:08:14
serg4321
Сорри, немного не до конца описал задачу. Вообщем можно ли добиться такого результата:
 select s.id, t.val, m.val
from 
(select id from m 
 union
 select id from t) s 
left join m on s.id= m.id 
left join t on s.id= t.id
order by s.id;

       ID  VAL VAL
---------- --- -----
         1     X
         2     X
         3 Y   X
         4 Y   
         5 Y   
только без двойных full scan'ов исходных таблиц?


with t2 as (select 2 a,id,val from m
  union all select 1,id,val from t
) select id
        ,min(val) keep (dense_rank first order by a) xy
        ,min(decode(a,2,val,null)) x
        ,min(decode(a,1,val,null)) y
 from t2
group by id
order by id;
serg4321
Дата: 26.02.2007 19:14:12
Спасибо большое!