2009-12-15 4 views
2

Моя проблема в Oracle, но, вероятно, независима от базы данных (?).Избегайте объединения путем присоединения?

У меня есть следующие таблицы:

аа

vid cb 
--- -- 
    1 10 
    2 15 

бб

vid cb 
--- -- 
    3 25 
    4 24 

** респ *

repid vid p 
----- --- -- 
    99 1 aa 
    99 2 aa 
    99 3 bb 
    99 4 bb 

Столбец p указывает, в какой таблице нужно получить строку. В действительности, aa и bb намного отличаются друг от друга, и p не соответствует имени таблицы, но дает возможность туда добраться. Пример - просто упрощение, когда у меня есть проблема. Обратите внимание, что в действительности существует более двух таблиц aa и bb (их 6). Я хочу, чтобы запрос, который возвращает это:

repid vid p cb 
----- --- -- -- 
    99 1 aa 10 
    99 2 aa 15 
    99 3 bb 25 
    99 4 bb 24 

следующих работ: (а)

select rep.vid, rep.p, cb 
from (
select 'aa' as p,vid,cb from aa 
union all 
select 'bb' as p, vid,cb from bb) u,rep 
where rep.p=u.p and rep.vid=u.vid 

(б)

select rep.vid, rep.p, 
    decode(rep.p, 'aa', (select cb from aa where vid=rep.vid), 
       'bb', (select cb from bb where vid=rep.vid)) cb 
from rep 

Но я хотел бы использовать запрос в вид, на котором может быть нажатие предиката.

Итак, вопрос 1 таков: допустимо ли следующее предикат. Вопрос 2: (даже если да для вопроса 1) есть способ сделать это без объединения, но с объединениями. Вопрос 3: Или просто, лучший способ?

Скрипт для создания данных:

create table bb (vid number(1), cb number(2)); 
create table aa (vid number(1), cb number(2)); 
create table rep(rid number(2), vid number(1), p varchar2(2)); 
insert into rep (rid,vid,p) values (99, 4,'bb'); 
insert into rep (rid,vid,p) values (99, 3,'bb'); 
insert into rep (rid,vid,p) values (99, 2,'aa'); 
insert into rep (rid,vid,p) values (99, 1,'aa'); 
insert into bb (vid,cb) values (4,24); 
insert into bb (vid,cb) values (3,25); 
insert into aa (vid,cb) values (2,15); 
insert into aa (vid,cb) values (1,10); 
commit; 
+0

У вас есть контроль над схемой? Я полагаю, вы не можете изменить ни одну из таблиц? – Burt

+0

Правильно: таблицы уже существуют, и я не могу их изменить. –

ответ

0

join можно указать несколько условий. Имя таблицы может быть одним. Например, если table1 имеет столбец TableName, который ссылается на другие таблицы, вы можете использовать:

select  * 
from  table1 t1 
left join table2 t2 
on   t1.TableName = 'table2' 
      and t1.id = t2.id 
left join table3 t3 
on   t1.TableName = 'table3' 
      and t1.id = t3.id 

Вы можете добавить произвольное количество таблиц таким образом.

Что касается третьего вопроса, всегда есть лучший способ. Вопрос в том, достаточно ли этого? Если нет, можете ли вы определить требования к приемлемому решению?

+0

Да, если в таблицах был столбец с именем tableName, это определенно помогло бы. Проблема в том, что они этого не делают. Я предполагаю, что одним из решений было бы создание представлений вокруг этих таблиц и включение имени таблицы (или эквивалента). –

+0

@Nicolas: Ваш стол «rep» содержит поле «pp» с именем табуляции? – Andomar

+0

Собственно, что бы вы имели вместо *, чтобы иметь столбец cb таблицы1 или cb таблицы2 в зависимости от значения p. Это большая часть проблемы: «объединение» столбцов из разных таблиц. –

2

У меня нет экземпляра Oracle, чтобы передать его, но попробовал ли что-нибудь с PostgreSQL, что может быть интересно?

Мой эксперимент с PostgreSQL предполагает, что на самом деле профсоюз работает лучше. Я создал представление, основанное на вашем запросе на объединение, и postgres смог нажать предикат, такой как «cb BETWEEN 12 AND 27» в сканирование aa и bb.

По Контрастом, я создал представление, которое использует присоединяется:

create view rep2 as 
    select rep.vid, p, coalesce(aa.cb, bb.cb) as cb 
    from rep 
     left join aa on aa.vid = rep.vid and rep.p = 'aa' 
     left join bb on bb.vid = rep.vid and rep.p = 'bb' 

Сейчас проблема заключается в том, что сливаются() блокирует предикат с участием сЬ толкают в сканов аа и бб.

 Смежные вопросы

  • Нет связанных вопросов^_^