powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / OUTER JOIN через (+)=
9 сообщений из 9, страница 1 из 1
OUTER JOIN через (+)=
    #32026865
skif
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Синтаксис 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)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

собственно, но пока такая роскошь не светит.. Что делать и как вы решаете такие вопросы?
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32026869
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
попробуй так
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)
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32026875
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
верхний вариант имеет некоторые недостатки - попробуй через 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
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32026911
skif
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да, последий вариант катит при любом раскладе. Особенно если DISTINCT вначале поставить... Спасибо.
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32026925
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а вот еще так попробуй

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)

на моем тестовом примере тоже заработало
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32027014
skif
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за последний вариант. Совет ...in (0, 2, 3) в принципе неверный.
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32027032
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
это почему не верный?
если не нравится 0 - то это для примера, ставишь туда такое значение которого не может быть и все.
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32027038
nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
или так
AND nvl(sif.source_t_id_id, 2) in (2, 3)
AND nvl(sia.source_t_id_id, 2) in (2, 3)
...
Рейтинг: 0 / 0
OUTER JOIN через (+)=
    #32027129
skif
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Объясняю, почему неверно. 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) то это превращается в кошмар. Источников - целая таблица....
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / OUTER JOIN через (+)=
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]