|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
Синтаксис ORACLE 8.1.7. Есть таблица физических лиц FIZ_L OBJ_ID_ID FIZ_L_ID FAMILY 1 1 Иванов 1 2 Иванов 2 3 Иванов Есть таблица S_I_FIZ_L, которая связана с таблицей FIZ_L по ключам и содержит дополнительную информацию, как то ссылку на источник, дату вставки записи etc. FIZ_L_ID_ID DATE_INS SOURCE_T_ID_ID some fields 1 01.01.2000 2 2 05.01.2000 3 3 01.01.1980 1 Есть таблица адресов ADDRESS OBJ_ID_ID ADDRESS_ID INDEX COUNTRY ....... 1 1 6456 4566 Есть таблица S_I_ADDRESS, которая содержит также служебную информацию и связана с ADDRESS ADDRESS_ID_ID DATE_INS SOURCE_T_ID_ID 1 01.01.1990 4 То есть общая логика такая: первичные таблицы (как то FIZ_L, ADDRESS) связаны между собой по первичным ключам OBJ_ID_ID. каждая из служебных связана с базовой S_I_FIZ_L.FIZ_L_ID_ID = FIZ_L.FIZ_L_ID и адреса таким же макаром, притом FIZ_L_ID уникален, для каждой записи в базовой таблице FIZ_L есть запись в дополнительной таблице S_I_xxxxxx. Задача: выбрать всех "ивановых", информацию брать только по источникам с кодом 2 и 3, выдать фамилию и адрес. Пишем запрос SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, schema.S_I_FIZ_L sif, schema.S_I_ADDRESS sia WHERE -- объединение базовых таблиц через OUTER JOIN, так как адрес у физлица может быть, а может и не быть ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID -- объединение FIZ_L со своей служебной таблицей AND sif.fiz_l_id_id = fl.fiz_l_id -- объединение таблицы адресов со своей служебной таблицей тоже по OUTER JOIN - законы ORACLE AND sia.address_id_id (+)= ad.address_id -- отсекаем теперь по источникам данных для таблицы FIZ_L AND sif.source_t_id_id in (2, 3) -- отсекаем теперь по источникам поступления адресов AND sia.source_t_id_id in (2, 3) Вроде бы все хорошо, но есть огромное НО. Согласно толмута ОРАКЛА, операция IN не разрешается для использования в условиях OUTER JOIN, и если у вас есть цепочка объединений table.id (+)= table2.id (+)= table3.id AND table3.ttt in (2,3), то вся геометрия летит коту под хвост и получается строгий INNER JOIN, что в данном случае нас не устраивает. Потому последняя строка условитя неверна. ....- потому что в даном примере есть запись по самому физлицу OBJ_ID_ID = 1 от источника 2, но адреса нету от источника 2, потому адрес показывать не надо, НО САМО ФИЗЛИЦО НАДО. В данном случае запись полностью будет удалена, что не есть верно..... Я решил переделать.... ..... AND (sia.source_t_id_id (+)= 2 OR sia.source_t_id_id (+)= 3) Не тут то было .... ERROR ORA...... OUTER JOIN NOT ALLOWED WITH "OR" and "IN" OPERATION.... Ну и что тогда делать? Я прекрасно понимаю, что можно перейти на ORACLE 9, воспользоваться table LEFT JOIN table2 ON table.ID = table2.ID AND table2.source_t_id_id in (2,3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ собственно, но пока такая роскошь не светит.. Что делать и как вы решаете такие вопросы? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.04.2002, 10:19 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
попробуй так SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, schema.S_I_FIZ_L sif, schema.S_I_ADDRESS sia WHERE ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID AND sif.fiz_l_id_id = fl.fiz_l_id AND sia.address_id_id (+)= ad.address_id AND nvl(sif.source_t_id_id, 0) in (0, 2, 3) AND nvl(sia.source_t_id_id, 0) in (0, 2, 3) ... |
|||
:
Нравится:
Не нравится:
|
|||
03.04.2002, 11:20 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
верхний вариант имеет некоторые недостатки - попробуй через union или union all SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, schema.S_I_FIZ_L sif, schema.S_I_ADDRESS sia WHERE ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID AND sif.fiz_l_id_id = fl.fiz_l_id AND sia.address_id_id (+)= ad.address_id AND sif.source_t_id_id(+)=2 AND sia.source_t_id_id(+)=2 union SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, schema.S_I_FIZ_L sif, schema.S_I_ADDRESS sia WHERE ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID AND sif.fiz_l_id_id = fl.fiz_l_id AND sia.address_id_id (+)= ad.address_id AND sif.source_t_id_id(+)=2 AND sia.source_t_id_id(+)=3 union SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, schema.S_I_FIZ_L sif, schema.S_I_ADDRESS sia WHERE ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID AND sif.fiz_l_id_id = fl.fiz_l_id AND sia.address_id_id (+)= ad.address_id AND sif.source_t_id_id(+)=3 AND sia.source_t_id_id(+)=2 union SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, schema.S_I_FIZ_L sif, schema.S_I_ADDRESS sia WHERE ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID AND sif.fiz_l_id_id = fl.fiz_l_id AND sia.address_id_id (+)= ad.address_id AND sif.source_t_id_id(+)=3 AND sia.source_t_id_id(+)=3 ... |
|||
:
Нравится:
Не нравится:
|
|||
03.04.2002, 11:39 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
да, последий вариант катит при любом раскладе. Особенно если DISTINCT вначале поставить... Спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.04.2002, 06:52 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
а вот еще так попробуй SELECT fl.FAMILY, ad.COUNTRY FROM schema.FIZ_L fl, schema.ADDRESS ad, (select * from schema.S_I_FIZ_L where source_t_id_id in (2,3)) sif, (select * from schema.S_I_ADDRESS where source_t_id_id in (2,3)) sia WHERE ad.OBJ_ID_ID (+)= fl.OBJ_ID_ID AND sif.fiz_l_id_id = fl.fiz_l_id AND sia.address_id_id (+)= ad.address_id AND nvl(sif.source_t_id_id, 0) in (0, 2, 3) AND nvl(sia.source_t_id_id, 0) in (0, 2, 3) на моем тестовом примере тоже заработало ... |
|||
:
Нравится:
Не нравится:
|
|||
04.04.2002, 07:44 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
Спасибо за последний вариант. Совет ...in (0, 2, 3) в принципе неверный. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 06:11 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
это почему не верный? если не нравится 0 - то это для примера, ставишь туда такое значение которого не может быть и все. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 07:27 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
или так AND nvl(sif.source_t_id_id, 2) in (2, 3) AND nvl(sia.source_t_id_id, 2) in (2, 3) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.04.2002, 07:46 |
|
OUTER JOIN через (+)=
|
|||
---|---|---|---|
#18+
Объясняю, почему неверно. NVL(выр1, выр2) будет работать в том случае, если выр1 IS null. Тогда действительно из обеих операций сравнения будет выбрано второе значение, и все прокатит. В моем случае это неверно, выр1 - это SOURCE_T_ID_ID, но оно не NULL, оно равно 1. И когда я сравниваю его с NVL(Source_t_id_id, 2), то получается, что оно как бы и не NULL, но как бы и не 2 или 3, и потому действует принцип отсечения строки. А вот с комбинаторикой UNION все классно, но если IN(2,3) превращается в IN(2, 3, 4, 5, 6,7 ....57, 67) то это превращается в кошмар. Источников - целая таблица.... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.04.2002, 10:03 |
|
|
start [/forum/topic.php?fid=52&fpage=2849&tid=1993394]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
39ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
35ms |
get tp. blocked users: |
1ms |
others: | 14ms |
total: | 131ms |
0 / 0 |