powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите, как правильно сравнивать между собой два набора данных
18 сообщений из 18, страница 1 из 1
Подскажите, как правильно сравнивать между собой два набора данных
    #39825612
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть некий каталог групп/типов услуг:
TARIFF_IDTYPE_IDCLASS11control22custom239custom349custom4102base1113type1124type2134type3202base2213type1302base3313type1325type2336type3346type4

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
with
CAT as
(
select 0 as tariff_id, 0 as type_id, '' as class from dual where 0=1
union all select 1,  1, 'control' from dual
union all select 2,  2, 'custom2' from dual
union all select 3,  9, 'custom3' from dual
union all select 4,  9, 'custom4' from dual
union all select 10, 2, 'base1' from dual
union all select 11, 3, 'type1' from dual
union all select 12, 4, 'type2' from dual
union all select 13, 4, 'type3' from dual
union all select 20, 2, 'base2' from dual
union all select 21, 3, 'type1' from dual
union all select 30, 2, 'base3' from dual
union all select 31, 3, 'type1' from dual
union all select 32, 5, 'type2' from dual
union all select 33, 6, 'type3' from dual
union all select 34, 6, 'type4' from dual
)
select * from CAT




Определенные типы услуг являются «контейнером» для других услуг, это услуги-пакеты.
Наборы этих услуг определены в таблице:
TARIFF_IDPARENT_ID11101210131021203130323033303430

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
with
PKG as
(
select 0 as tariff_id, 0 as parent_id from dual where 0=1
union all select 11, 10 from dual
union all select 12, 10 from dual
union all select 13, 10 from dual
union all select 21, 20 from dual
union all select 31, 30 from dual
union all select 32, 30 from dual
union all select 33, 30 from dual
union all select 34, 30 from dual
)
select * from PKG




В БД есть список клиентов:
CLIENT_IDNAME1client12client23client34client45client5

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with
CLN as
(
select 0 as client_id, '' as name from dual where 0=1
union all select 1, 'client1' from dual
union all select 2, 'client2' from dual
union all select 3, 'client3' from dual
union all select 4, 'client4' from dual
union all select 5, 'client5' from dual
)
select * from CLN




И у этих клиентов подключены услуги:
CLIENT_IDSERVICE_IDTARIFF_ID1100111101011111111121211131322001222020330013330303331315502255033551212552121

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
with
SVC as (
select 0 as client_id, 0 as service_id, 0 as tariff_id from dual where 0=1
union all select 1, 100, 1 from dual
union all select 1, 110, 10 from dual
union all select 1, 111, 11 from dual
union all select 1, 112, 12 from dual
union all select 1, 113, 13 from dual
union all select 2, 200, 1 from dual
union all select 2, 220, 20 from dual
union all select 3, 300, 1 from dual
union all select 3, 330, 30 from dual
union all select 3, 331, 31 from dual
union all select 5, 502, 2 from dual
union all select 5, 503, 3 from dual
union all select 5, 512, 12 from dual
union all select 5, 521, 21 from dual
)
select * from SVC




Мне нужно для пакетов услуг определить расхождения с шаблонами.
Например в приведенном примере:
Клиент 1 — все хорошо, у клиента подключен пакет base1 и все входящие в состав этого пакета услуги 111-113.
Клиент 2 — у клиента подключен пакет base2, однако не подключены услуги, которые должны входить в этот пакет (тариф 21).
Клиент 3 - у клиента подключен пакет base3, однако подключена только одна услуга пакета 331, еще три услуги не подключены (тарифы 32-34).
Клиент 4 - у клиента не подключено никаких услуг.
Клиент 5 - две услуги (512, 521) должны входить в состав пакета, однако сами пакеты не подключены.

По итогам обработки мне нужно сделать следующее:
Клиенты 1, 4 - пропустить.
Клиенты 2, 3 - подключить недостающие услуги пакета.
Клиент 5 - зафиксировать ошибку, у одного клиента не должны быть подключены разные пакеты одновременно.

Наверное это типичная задача на сравнение двух наборов.
Однако у меня с ее решением есть некоторые сложности.

Вначале я получаю список клиентов и соответствующих им пакетов:
CLIENT_IDBASE_ID1102203305

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
with ...
select CLN.CLIENT_ID, BAS.BASE_ID
from CLN
join SVC on (SVC.CLIENT_ID = CLN.CLIENT_ID)
join CAT on (CAT.TARIFF_ID = SVC.TARIFF_ID)
left join (select distinct PARENT_ID from PKG) PRN on (PRN.PARENT_ID = SVC.TARIFF_ID)
left join (
select CLIENT_ID, min(TARIFF_ID) as BASE_ID
from SVC join (select distinct PARENT_ID as TARIFF_ID from PKG) PRN using (TARIFF_ID)
group by CLIENT_ID
) BAS on (BAS.CLIENT_ID = SVC.CLIENT_ID)
left join PKG on (PKG.TARIFF_ID = SVC.TARIFF_ID and PKG.PARENT_ID = BAS.BASE_ID)
group by CLN.CLIENT_ID, BAS.BASE_ID



Для клиентов 1-3 базовый пакет определен правильно, клиента 4 в списке нет (поскольку нет услуг), а для клиента 5 базовый пакет не задан.

Теперь для этого списка я получаю эталонный набор услуг:
CLIENT_IDTARIFF_IDIS_PARENT11011111121132201221311330133133233351

Код: 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.
with ...
, TPL as (
select CLN.CLIENT_ID, BAS.BASE_ID
from CLN
join SVC on (SVC.CLIENT_ID = CLN.CLIENT_ID)
join CAT on (CAT.TARIFF_ID = SVC.TARIFF_ID)
left join (select distinct PARENT_ID from PKG) PRN on (PRN.PARENT_ID = SVC.TARIFF_ID)
left join (
select CLIENT_ID, min(TARIFF_ID) as BASE_ID
from SVC join (select distinct PARENT_ID as TARIFF_ID from PKG) PRN using (TARIFF_ID)
group by CLIENT_ID
) BAS on (BAS.CLIENT_ID = SVC.CLIENT_ID)
left join PKG on (PKG.TARIFF_ID = SVC.TARIFF_ID and PKG.PARENT_ID = BAS.BASE_ID)
group by CLN.CLIENT_ID, BAS.BASE_ID
)
, LST as (
select TPL.CLIENT_ID, BASE_ID as TARIFF_ID, 1 as IS_PARENT
from TPL
union all
select TPL.CLIENT_ID, PKG.TARIFF_ID, null
from TPL
join PKG on (PKG.PARENT_ID = TPL.BASE_ID)
order by CLIENT_ID, TARIFF_ID
)
select * from LST




Как мне теперь выполнить сравнение наборов?
Я пробовал через full outer join:

Код: 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.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
with
CAT as
(
select 0 as tariff_id, 0 as type_id, '' as class from dual where 0=1
union all select 1,  1, 'control' from dual
union all select 2,  2, 'custom2' from dual
union all select 3,  9, 'custom3' from dual
union all select 4,  9, 'custom4' from dual
union all select 10, 2, 'base1' from dual
union all select 11, 3, 'type1' from dual
union all select 12, 4, 'type2' from dual
union all select 13, 4, 'type3' from dual
union all select 20, 2, 'base2' from dual
union all select 21, 3, 'type1' from dual
union all select 30, 2, 'base3' from dual
union all select 31, 3, 'type1' from dual
union all select 32, 5, 'type2' from dual
union all select 33, 6, 'type3' from dual
union all select 34, 6, 'type4' from dual
),
PKG as (
select 0 as tariff_id, 0 as parent_id from dual where 0=1
union all select 11, 10 from dual
union all select 12, 10 from dual
union all select 13, 10 from dual
union all select 21, 20 from dual
union all select 31, 30 from dual
union all select 32, 30 from dual
union all select 33, 30 from dual
union all select 11, 30 from dual
),
CLN as (
select 0 as client_id, '' as name from dual where 0=1
union all select 1, 'client1' from dual
union all select 2, 'client2' from dual
union all select 3, 'client3' from dual
union all select 4, 'client4' from dual
union all select 5, 'client5' from dual
),
SVC as (
select 0 as client_id, 0 as service_id, 0 as tariff_id from dual where 0=1
union all select 1, 100, 1 from dual
union all select 1, 110, 10 from dual
union all select 1, 111, 11 from dual
union all select 1, 112, 12 from dual
union all select 1, 113, 13 from dual
union all select 2, 200, 1 from dual
union all select 2, 220, 20 from dual
union all select 3, 300, 1 from dual
union all select 3, 330, 30 from dual
union all select 3, 331, 31 from dual
union all select 5, 502, 2 from dual
union all select 5, 503, 3 from dual
union all select 5, 512, 12 from dual
union all select 5, 521, 21 from dual
),
TPL as (
select CLN.CLIENT_ID, BAS.BASE_ID
from CLN
join SVC on (SVC.CLIENT_ID = CLN.CLIENT_ID)
join CAT on (CAT.TARIFF_ID = SVC.TARIFF_ID)
left join (select distinct PARENT_ID from PKG) PRN on (PRN.PARENT_ID = SVC.TARIFF_ID)
left join (
select CLIENT_ID, min(TARIFF_ID) as BASE_ID
from SVC join (select distinct PARENT_ID as TARIFF_ID from PKG) PRN using (TARIFF_ID)
group by CLIENT_ID
) BAS on (BAS.CLIENT_ID = SVC.CLIENT_ID)
left join PKG on (PKG.TARIFF_ID = SVC.TARIFF_ID and PKG.PARENT_ID = BAS.BASE_ID)
group by CLN.CLIENT_ID, BAS.BASE_ID
),
LST as (
select TPL.CLIENT_ID, BASE_ID as TARIFF_ID, 1 as IS_PARENT
from TPL
union all
select TPL.CLIENT_ID, PKG.TARIFF_ID, null
from TPL
join PKG on (PKG.PARENT_ID = TPL.BASE_ID)
order by CLIENT_ID, TARIFF_ID
),
AGR as (
select CLN.CLIENT_ID, SVC.SERVICE_ID, SVC.TARIFF_ID, CAT.TYPE_ID, CAT.CLASS
, PRN.PARENT_ID
, BAS.BASE_ID
, PKG.TARIFF_ID as PKG_TARIFF_ID
, PKG.PARENT_ID as PKG_PARENT_ID
from CLN
join SVC on (SVC.CLIENT_ID = CLN.CLIENT_ID)
join CAT on (CAT.TARIFF_ID = SVC.TARIFF_ID)
left join (select distinct PARENT_ID from PKG) PRN on (PRN.PARENT_ID = SVC.TARIFF_ID)
left join (
select CLIENT_ID, min(TARIFF_ID) as BASE_ID
from SVC join (select distinct PARENT_ID as TARIFF_ID from PKG) PRN using (TARIFF_ID)
group by CLIENT_ID
) BAS on (BAS.CLIENT_ID = SVC.CLIENT_ID)
left join PKG on (PKG.TARIFF_ID = SVC.TARIFF_ID and PKG.PARENT_ID = BAS.BASE_ID)
)
select coalesce(LST.CLIENT_ID,AGR.CLIENT_ID) as CLIENT_ID
, coalesce(LST.TARIFF_ID,AGR.TARIFF_ID) as TARIFF_ID
, case
    when (LST.CLIENT_ID is null and AGR.CLIENT_ID is not null) and (LST.TARIFF_ID is null and AGR.TARIFF_ID is not null) then 'del'
    when (LST.CLIENT_ID is not null and AGR.CLIENT_ID is null) and (LST.TARIFF_ID is not null and AGR.TARIFF_ID is null) then 'ins'
    else '?'
  end as DIFF
, AGR.CLASS
, AGR.TYPE_ID
, AGR.SERVICE_ID
, AGR.PARENT_ID
from LST full join AGR on (AGR.CLIENT_ID = LST.CLIENT_ID and AGR.TARIFF_ID = LST.TARIFF_ID)
where AGR.PKG_TARIFF_ID is null
order by 1, 2



Как мне кажется, это что-то близкое к решению, но глаз у меня уже замылился и я никак не соображу, как правильно сравнивать наборы.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39825648
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Мне нужно для пакетов услуг определить расхождения с шаблонами.Это же вполне бизнес-задача, за которую кто-то хочет незаслуженно получить бизнес-деньги, не так ли?
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39825704
Tesamid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alibek B., добрый день!

авторКак мне теперь выполнить сравнение наборов?
Как понял из вашего сообщения, вам удалось получить две выборки: эталон и фактическую.
Можно попробовать выполнить операцию (эталон) minus (факт) над этими множествами.
Таким образом удастся определить недостающие услуги для 2, 3 и убедиться, что 1 и 4 обладают полным набором.
Для того, чтобы найти клиентов у которых услуги подключены без пакета нужно сделать (факт) minus (эталон),
предварительно отфильтровав оба множества, чтобы остались только услуги-пакеты.
В результате окажутся клиенты у которых нет ни одной подключенной услуги-пакета.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39825739
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tesamid(эталон) minus (факт)
(факт) minus (эталон)
Я как раз и думал заменить два сравнения на один full join, но не получилось.
Или это принципиально не получиться сделать за раз?
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39825821
Tesamid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alibek B.Я как раз и думал заменить два сравнения на один full join, но не получилось.
Или это принципиально не получиться сделать за раз?

Не совсем понял идею сравнения двух наборов с помощью full_join.
И если правильно понял условие, то можно написать промежуточные запросы в более простой форме,
вот примерное решение задачи, если нужны какие-то реквизиты тарифов или клиентов, то просто джойним в нужных местах.

Код: 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.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
with
PKG as
(
select 0 as tariff_id, 0 as parent_id from dual where 0=1
union all select 11, 10 from dual
union all select 12, 10 from dual
union all select 13, 10 from dual
union all select 21, 20 from dual
union all select 31, 30 from dual
union all select 32, 30 from dual
union all select 33, 30 from dual
union all select 34, 30 from dual
),
CLN as
(
select 0 as client_id, '' as name from dual where 0=1
union all select 1, 'client1' from dual
union all select 2, 'client2' from dual
union all select 3, 'client3' from dual
union all select 4, 'client4' from dual
union all select 5, 'client5' from dual
),
SVC as (
select 0 as client_id, 0 as service_id, 0 as tariff_id from dual where 0=1
union all select 1, 100, 1 from dual
union all select 1, 110, 10 from dual
union all select 1, 111, 11 from dual
union all select 1, 112, 12 from dual
union all select 1, 113, 13 from dual
union all select 2, 200, 1 from dual
union all select 2, 220, 20 from dual
union all select 3, 300, 1 from dual
union all select 3, 330, 30 from dual
union all select 3, 331, 31 from dual
union all select 5, 502, 2 from dual
union all select 5, 503, 3 from dual
union all select 5, 512, 12 from dual
union all select 5, 521, 21 from dual
),
-- получаем все соответствия клиентов и пакетов
pkg_to_client as
(select cln.client_id , pkg.parent_id
 from cln
 join svc on cln.client_id = svc.client_id
 join pkg on svc.tariff_id = pkg.parent_id 
),
-- объединяем услуги-пакеты клиента и услуги клиента, входящие в пакет - это наш эталон
etalon_svc as
(select client_id, parent_id tariff_id
 from pkg_to_client
 union all
 select pkg_to_client.client_id, pkg.tariff_id
 from pkg_to_client
 join pkg on pkg_to_client.parent_id = pkg.parent_id
)
select client_id, tariff_id, state_ -- находим услуги клиентов, которые забыли подключить вместе с пакетом
from (
    
        select client_id, tariff_id, 'Забыли подключить' state_
        from etalon_svc
        minus
        select client_id, tariff_id, 'Забыли подключить' state_
        from svc
    
    ) t_no_service
union all
select client_id, tariff_id, state_ -- находим клиентов и услуги, которые подключены без пакета 
from (
        select client_id, tariff_id, 'Подключили без пакета' state_
        from svc
        minus
        select client_id, tariff_id, 'Подключили без пакета' state_
        from etalon_svc
    ) t_no_package
    

...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39826361
SkilledJunior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alibek B.Я как раз и думал заменить два сравнения на один full join, но не получилось.
Или это принципиально не получиться сделать за раз?
Элементарно.
Код: 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.
with a (f1, f2) as
(
  select 1 , 100 from dual union all
  select 1 , 200 from dual union all
  select 1 , 300 from dual union all
  select 2 , 100 from dual union all
  select 2 , 200 from dual union all
  select 2 , 400 from dual union all
  select 2 , 500 from dual
),
   b (f1, f2) as
(
  select 1 , 100 from dual union all
  select 1 , 200 from dual union all
  select 1 , 300 from dual union all
  select 2 , 100 from dual union all
  select 2 , 200 from dual union all
  select 2 , 300 from dual union all
  select 2 , 400 from dual union all
  select 2 , 500 from dual
),
   t as
(
  select a.f1 af1, b.f1 bf1, a.f2 af2, b.f2 bf2
  from a full join b on a.f1=b.f1 and a.f2=b.f2
)
select * from t where af1 is null or af2 is null or bf1 is null or bf2 is null

...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39826382
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SkilledJuniorЭлементарно.Демонстрация абстрактного синтаксиса full join есть в документации, а предметного в исходном сообщении темы.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39826784
SkilledJunior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-,

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

Код: 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.
with a (f1, f2) as
( -- факт
  select 1 ,  1 from dual union all
  select 1 , 10 from dual union all
  select 1 , 11 from dual union all
  select 1 , 12 from dual union all
  select 1 , 13 from dual union all
  --
  select 2 ,  1 from dual union all
  select 2 , 20 from dual union all
  --
  select 3 , 1 from dual union all
  select 3 , 30 from dual union all
  select 3 , 31 from dual union all
  --
  select 5 ,  2 from dual union all
  select 5 ,  3 from dual union all
  select 5 , 12 from dual union all
  select 5 , 21 from dual
),
   b (f1, f2) as
( -- эталон
  select 1 ,  1 from dual union all
  select 1 , 10 from dual union all
  select 1 , 11 from dual union all
  select 1 , 12 from dual union all
  select 1 , 13 from dual union all
  --
  select 2 ,  1 from dual union all
  select 2 , 20 from dual union all
  select 2 , 21 from dual union all
  --
  select 3 ,  1 from dual union all
  select 3 , 11 from dual union all
  select 3 , 30 from dual union all
  select 3 , 31 from dual union all
  select 3 , 32 from dual union all
  select 3 , 33 from dual union all
  --
  select 4 , null from dual union all
  --
  select 5 ,  1 from dual
),
   t as
(
  select a.f1 af1, a.f2 af2, b.f1 bf1, b.f2 bf2
  from a full join b on a.f1=b.f1 and a.f2=b.f2
)
select coalesce(af1, bf1) as client, t.*
  from t where af1 is null or af2 is null or bf1 is null or bf2 is null
 order by coalesce(af1, bf1), coalesce(af2, bf2)

...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827231
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tesamidвот примерное решение задачи, если нужны какие-то реквизиты тарифов или клиентов, то просто джойним в нужных местах.
Да, истина где-то рядом, но критерии сравнения для запроса у меня не получается придумать.
Наверное буду решать построчным анализом на клиенте.

SkilledJuniorЭлементарно.
Не вижу принципиальных отличий от того, что я написал в самом начале.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827249
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Tesamidвот примерное решение задачи, если нужны какие-то реквизиты тарифов или клиентов, то просто джойним в нужных местах.
Да, истина где-то рядом, но критерии сравнения для запроса у меня не получается придумать.
Наверное буду решать построчным анализом на клиенте.Даже это лучше делать на сервере:
не будет сетевых задержек и дополнительной нагрузки на сеть.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827284
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, возможно и так.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827415
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Наверное это типичная задача на сравнение двух наборов.Скорее это типичная задача на outer join partition by.

Поскольку для каждой встречающейся комбинации (клиент, пакет) надо присоединить все услуги этого пакета и посмотреть чего не хватает.
Тонкость в том, что join partition by дублирует некоторый фиксированный набор для каждой комбинации. Поэтому приходится дублировать для (клиент, пакет) услуги всех пакетов и потом оставлять нужный пакет фильтруя
Код: plaintext
where t.parent_id = pkg.parent_id
.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
select t.client_id,
       pkg.parent_id,
       pkg.tariff_id missing_tariff_id
  from    pkg
       left join
          (select svc.*, pkg.parent_id
             from svc join pkg on svc.tariff_id = pkg.tariff_id) t
       partition by (t.client_id, t.parent_id)
       on pkg.tariff_id = t.tariff_id
 where t.parent_id = pkg.parent_id and t.tariff_id is null;

 CLIENT_ID  PARENT_ID MISSING_TARIFF_ID
---------- ---------- -----------------
         3         30                32
         3         30                33
         3         30                34
         5         10                11
         5         10                13


Вероятно, ты предварительно еще захочешь сделать проверку на число пакетов на клиента, но я, думаю, справишься.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827438
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КобанчегСкорее это типичная задача на outer join partition by.Принимая во внимание особенности задания иерархии надо добавить строки для "корней" привязанные к null, чтоб client 2 не пропадал.
Код: 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.
select t.client_id,
       pkg.parent_id,
       pkg.tariff_id missing_tariff_id
  from    pkg
       left join
          (select svc.*, nvl(pkg.parent_id, svc.tariff_id) parent_id
             from    svc
                  join
                     (select * from pkg
                      union all
                      select distinct parent_id, null from pkg) pkg
                  on svc.tariff_id = pkg.tariff_id) t
       partition by(t.client_id, t.parent_id)
       on pkg.tariff_id = t.tariff_id
 where t.parent_id = pkg.parent_id and t.tariff_id is null
order by 1, 2, 3;

 CLIENT_ID  PARENT_ID MISSING_TARIFF_ID
---------- ---------- -----------------
         2         20                21
         3         30                32
         3         30                33
         3         30                34
         5         10                11
         5         10                13


Кобанчегпредварительно еще захочешь сделать проверку на число пакетов на клиентаУчитывая, что outer join partition by как раз переписывается через дополнительное соединение с distinct (или группировкой),
то здесь можно пойти этим путём, включив во вспомогательную inline view проверку на число parent.
Код: 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.
select client_id,
       case
          when max(cnt_parent) = 2 then 'more than one bundle: '
            || max(parent_list)
          when count(missing_tariff_id) > 0 then 'missing tariffs: '
            || listagg(missing_tariff_id, ', ') within group (order by missing_tariff_id)
          else 'OK'
       end
          error_info
  from (select t.*, nvl2(svc.tariff_id, null, pkg.tariff_id) missing_tariff_id
          from (select client_id,
                       count(*) cnt_parent,
                       max(parent_id) parent_id,
                       listagg(parent_id, ', ') within group (order by client_id) parent_list
                  from (select distinct svc.client_id, nvl(pkg.parent_id, svc.tariff_id) parent_id
                          from    svc
                               join
                                  (select * from pkg
                                   union all
                                   select distinct parent_id, null from pkg) pkg
                               on svc.tariff_id = pkg.tariff_id)
                group by client_id) t
               join pkg
                  on t.parent_id = pkg.parent_id
               left join svc
                  on pkg.tariff_id = svc.tariff_id and t.client_id = svc.client_id)
group by client_id
order by 1;

 CLIENT_ID ERROR_INFO
---------- --------------------------------------------------
         1 OK
         2 missing tariffs: 21
         3 missing tariffs: 32, 33, 34
         5 more than one bundle: 10, 20
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827440
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег
Код: plsql
1.
when max(cnt_parent) > 1 then 'more than one bundle: '
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827455
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, завтра поэкспериментирую.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827466
SkilledJunior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SkilledJuniorНе вижу принципиальных отличий от того, что я написал в самом начале.
Если соберешь эталон соответствующим образом, тогда сможешь сравнивать, а так у тебя факт имеет одну структуру, эталон другую.

Здесь пример, какой эталон ты должен был собрать на представленный тобой факт 21909017
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827472
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шож ты тычешь свой full join по поводу и без, юное бездарование.
Господину Алибеку не надо проверять на наличие несуществующих услуг, ему надо найти криво оформлнные пакеты услуг.
Перед рассуждениями про сферические эталоны в вакууме попытайся еще раз осилить постановку.
...
Рейтинг: 0 / 0
Подскажите, как правильно сравнивать между собой два набора данных
    #39827477
SkilledJunior
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
КобанчегШож ты тычешь свой full join по поводу и без, юное бездарование.
Господину Алибеку не надо проверять на наличие несуществующих услуг, ему надо найти криво оформлнные пакеты услуг.
Перед рассуждениями про сферические эталоны в вакууме попытайся еще раз осилить постановку.
Смешные вы, ну мастерите дальше ...
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите, как правильно сравнивать между собой два набора данных
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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