powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / join по одному из условий
8 сообщений из 8, страница 1 из 1
join по одному из условий
    #39901773
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня есть два набора данных, которые нужно соединить между собой по любому из нескольких критериев.
Если упростить, то наборы данных такие:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
with SL as
(
  select 0 IDX, 0 CNT, 0 CUSTOMER_ID, 0 SERVICE_ID, '' LOGIN, 0 STATUS, 0 AV, '' IP from DUAL where 0=1
  union all select 1, 4, 8434, 153083, '101-3129', 1, 452953, 'xx.yy.zz.59' from DUAL
  union all select 2, 4, 8434, 153084, '201-0051', 1, 452954, 'xx.yy.zz.60' from DUAL
  union all select 3, 4, 8434, 153085, '201-0067', 1, 452955, 'xx.yy.zz.61' from DUAL
  union all select 4, 4, 8434, 156165, '201-0135', 1, 452952, 'xx.yy.zz.69' from DUAL
)
select * from SL;

with IP as
(
  select 0 IDX, 0 CNT, 0 CUSTOMER_ID, 0 SERVICE_ID, '' IP, 0 STATUS, 0 PARENT from DUAL where 0=1
  union all select 1, 4, 8434, 346683, 'xx.yy.zz.69', 10, 156165 from DUAL
  union all select 2, 4, 8434, 346684, 'xx.yy.zz.59', 10, 153083 from DUAL
  union all select 3, 4, 8434, 346685, 'xx.yy.zz.60', 10, 153084 from DUAL
  union all select 4, 4, 8434, 346686, 'xx.yy.zz.61', 10, 153085 from DUAL
)
select * from IP;


Каждый из наборов упорядочен по своему критерию (пронумерован через IDX).
CUSTOMER_ID группирует наборы, CNT указывает на количество строк внутри группы (в тестовых наборах для упрощения только одна группа).
Правила соединения у меня следующие:
1. Если IP.PARENT=SL.SERVICE_ID, то соединить строки этих наборов.
2. Из оставшихся записей наборы состоящие из одной строки (CNT=1) соединяются между собой.
3. Из оставшихся записей (в группе больше одной строки и для IP.PARENT нет пары) строки наборов соединяются по совпадению поля IP.
4. И наконец если все равно остались какие-то записи, то они соединяются по порядковому номеру.

У меня используется такой запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
select
  SL.CUSTOMER_ID
, SL.SERVICE_ID
, SL.LOGIN
, SL.STATUS
, SL.IP
, SL.AV
, IP.SERVICE_ID as IP_SERVICE
, IP.IP as IP_VALUE
, IP.STATUS as IP_STATUS
, IP.PARENT as IP_PARENT
from SL full join IP
  on
  (
     (SL."SERVICE_ID" = IP."PARENT")
  or (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."CNT" = 1 and IP."CNT" = 1)
  or (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."IP" = IP."IP")
  or (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."IP" != IP."IP" and SL."IDX" = IP."IDX")
  )
where (SL.IP is not null or IP.IP is not null);


Но на этом тестовом наборе он удваивает строки (потому что одновременно совпадают условия 3 и 4).
Если условие 4 закомментировать, то строки не удваиваются. Но хотелось бы его сохранить, потому что такое условие иногда случается.
Не подскажите, как тут можно исключить дубли?
...
Рейтинг: 0 / 0
join по одному из условий
    #39901792
alex-ls
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну так добавьте. условие 4, если условие 3 НЕ выполняется
...
Рейтинг: 0 / 0
join по одному из условий
    #39901805
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня именно так и сделано.
Дубли появляются потому, что есть несовпадающие IP и совпадающие IDX.
...
Рейтинг: 0 / 0
join по одному из условий
    #39901872
alex-ls
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
У меня именно так и сделано.
Дубли появляются потому, что есть несовпадающие IP и совпадающие IDX.

значит показываются строки, совпадающие например по 2 и 4 или по 1 и 4
...
Рейтинг: 0 / 0
join по одному из условий
    #39901951
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну как бы в том и вопрос.
Если добавить в запрос вывод столбцов SL.IDX, IP.IDX, то становится понятно, что строки потому и удваиваются, что для двух строк в моем примере одновременно выполняются условия 3 и 4 (совпадающие IP и несовпадающие IP с совпадающими IDX).
Но как поменять условия, чтобы исключить их одновременное выполнение, я не соображу.
...
Рейтинг: 0 / 0
join по одному из условий
    #39901958
Азагаш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Уже похоже на говнокод, но может 1 or (not(1) and 2) or (not(1) and not(2) and 3)?
...
Рейтинг: 0 / 0
join по одному из условий
    #39901964
Азагаш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Двоится не из-за выполнения нескольких условий а из-за концепции «оставшихся записей». Оставшихся от чего? Соединяются все записи со всеми, если подходят условия. Никто нигде не «остается»
...
Рейтинг: 0 / 0
join по одному из условий
    #39902490
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
with SL as (
  select 0 IDX, 0 CNT, 0 CUSTOMER_ID, 0 SERVICE_ID, '' LOGIN, 0 STATUS, 0 AV, '' IP from DUAL where 0=1
  union all select 1, 4, 8434, 153083, '101-3129', 1, 452953, 'xx.yy.zz.59' from DUAL
  union all select 2, 4, 8434, 153084, '201-0051', 1, 452954, 'xx.yy.zz.60' from DUAL
  union all select 3, 4, 8434, 153085, '201-0067', 1, 452955, 'xx.yy.zz.61' from DUAL
  union all select 4, 4, 8434, 156165, '201-0135', 1, 452952, 'xx.yy.zz.69' from DUAL
)
 , IP as (
  select 0 IDX, 0 CNT, 0 CUSTOMER_ID, 0 SERVICE_ID, '' IP, 0 STATUS, 0 PARENT from DUAL where 0=1
  union all select 1, 4, 8434, 346683, 'xx.yy.zz.69', 10, 156165 from DUAL
  union all select 2, 4, 8434, 346684, 'xx.yy.zz.59', 10, 153083 from DUAL
  union all select 3, 4, 8434, 346685, 'xx.yy.zz.60', 10, 153084 from DUAL
  union all select 4, 4, 8434, 346686, 'xx.yy.zz.61', 10, 153085 from DUAL
)
--
select
  CASE WHEN (SL."SERVICE_ID" = IP."PARENT") THEN 'Case-1' END AS case_1
, CASE WHEN (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."CNT" = 1 and IP."CNT" = 1) THEN 'Case-2' END AS case_2
, CASE WHEN (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."IP" = IP."IP") THEN 'Case-3' END AS case_3
, CASE WHEN (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."IP" != IP."IP" and SL."IDX" = IP."IDX") THEN 'Case-4' END AS case_4
, SL.CUSTOMER_ID
, SL.SERVICE_ID
, SL.LOGIN
, SL.STATUS
, SL.IP
, SL.AV
, IP.SERVICE_ID as IP_SERVICE
, IP.IP as IP_VALUE
, IP.STATUS as IP_STATUS
, IP.PARENT as IP_PARENT
from SL full join IP
  on
  (
     (SL."SERVICE_ID" = IP."PARENT")
  or (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."CNT" = 1 and IP."CNT" = 1)
  or (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."IP" = IP."IP")
  or (SL."CUSTOMER_ID" = IP."CUSTOMER_ID" and SL."IP" != IP."IP" and SL."IDX" = IP."IDX")
  )
where (SL.IP is not null or IP.IP is not null);

CASE_1 CASE_2 CASE_3 CASE_4 CUSTOMER_ID SERVICE_ID LOGIN        STATUS IP                  AV IP_SERVICE IP_VALUE     IP_STATUS  IP_PARENT
------ ------ ------ ------ ----------- ---------- -------- ---------- ----------- ---------- ---------- ----------- ---------- ----------
-      -      -      Case-4        8434     153083 101-3129          1 xx.yy.zz.59     452953     346683 xx.yy.zz.69         10     156165
Case-1 -      Case-3 -             8434     153083 101-3129          1 xx.yy.zz.59     452953     346684 xx.yy.zz.59         10     153083
-      -      -      Case-4        8434     153084 201-0051          1 xx.yy.zz.60     452954     346684 xx.yy.zz.59         10     153083
Case-1 -      Case-3 -             8434     153084 201-0051          1 xx.yy.zz.60     452954     346685 xx.yy.zz.60         10     153084
-      -      -      Case-4        8434     153085 201-0067          1 xx.yy.zz.61     452955     346685 xx.yy.zz.60         10     153084
Case-1 -      Case-3 -             8434     153085 201-0067          1 xx.yy.zz.61     452955     346686 xx.yy.zz.61         10     153085
Case-1 -      Case-3 -             8434     156165 201-0135          1 xx.yy.zz.69     452952     346683 xx.yy.zz.69         10     156165
-      -      -      Case-4        8434     156165 201-0135          1 xx.yy.zz.69     452952     346686 xx.yy.zz.61         10     153085

8 rows selected. 


Изучайте вашу ситуацию. Надеюсь, так станет понятнее.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / join по одному из условий
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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