Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Запрос  [new]
serg4321
Member

Откуда: Санкт-Петербург
Сообщений: 133
Добрый всем вечер!

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

Есть таблица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 |
--------------------------------------------------------------------------------

Заранее спасибо за ответы.
26 фев 07, 18:47    [3834218]     Ответить | Цитировать Сообщить модератору
 Re: Запрос  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
select m.id, nvl(t.val, m.val) value
from m ,t
where t.id (+) = m.id
order by m.id;
Ну и (вообще) план исследовать смысл имеет на более представительных данных
26 фев 07, 18:55    [3834252]     Ответить | Цитировать Сообщить модератору
 Re: Запрос  [new]
serg4321
Member

Откуда: Санкт-Петербург
Сообщений: 133
Сорри, немного не до конца описал задачу. Вообщем можно ли добиться такого результата:
 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'ов исходных таблиц?
26 фев 07, 19:04    [3834282]     Ответить | Цитировать Сообщить модератору
 Re: Запрос  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
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;
26 фев 07, 19:08    [3834304]     Ответить | Цитировать Сообщить модератору
 Re: Запрос  [new]
serg4321
Member

Откуда: Санкт-Петербург
Сообщений: 133
Спасибо большое!
26 фев 07, 19:14    [3834328]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить