Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Подскажите, как правильно сравнивать между собой два набора данных  [new]
Alibek B.
Member

Откуда:
Сообщений: 3189
Есть некий каталог групп/типов услуг:
TARIFF_IDTYPE_IDCLASS
11control
22custom2
39custom3
49custom4
102base1
113type1
124type2
134type3
202base2
213type1
302base3
313type1
325type2
336type3
346type4

+

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_ID
1110
1210
1310
2120
3130
3230
3330
3430

+

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_IDNAME
1client1
2client2
3client3
4client4
5client5

+

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_ID
11001
111010
111111
111212
111313
22001
222020
33001
333030
333131
55022
55033
551212
552121

+

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_ID
110
220
330
5

+

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_PARENT
1101
111
112
113
2201
221
311
3301
331
332
333
51

+

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:
+

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


Как мне кажется, это что-то близкое к решению, но глаз у меня уже замылился и я никак не соображу, как правильно сравнивать наборы.
11 июн 19, 22:07    [21907073]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Elic
Member

Откуда: 1984. Выбраковка финно-угром продолжается. КЯЗ
Сообщений: 29189
Alibek B.
Мне нужно для пакетов услуг определить расхождения с шаблонами.
Это же вполне бизнес-задача, за которую кто-то хочет незаслуженно получить бизнес-деньги, не так ли?
12 июн 19, 07:27    [21907162]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Tesamid
Member

Откуда:
Сообщений: 8
Alibek B., добрый день!

автор
Как мне теперь выполнить сравнение наборов?

Как понял из вашего сообщения, вам удалось получить две выборки: эталон и фактическую.
Можно попробовать выполнить операцию (эталон) minus (факт) над этими множествами.
Таким образом удастся определить недостающие услуги для 2, 3 и убедиться, что 1 и 4 обладают полным набором.
Для того, чтобы найти клиентов у которых услуги подключены без пакета нужно сделать (факт) minus (эталон),
предварительно отфильтровав оба множества, чтобы остались только услуги-пакеты.
В результате окажутся клиенты у которых нет ни одной подключенной услуги-пакета.
12 июн 19, 11:54    [21907242]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Alibek B.
Member

Откуда:
Сообщений: 3189
Tesamid
(эталон) minus (факт)
(факт) minus (эталон)

Я как раз и думал заменить два сравнения на один full join, но не получилось.
Или это принципиально не получиться сделать за раз?
12 июн 19, 13:34    [21907286]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Tesamid
Member

Откуда:
Сообщений: 8
Alibek B.
Я как раз и думал заменить два сравнения на один full join, но не получилось.
Или это принципиально не получиться сделать за раз?


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

+
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
    
12 июн 19, 18:34    [21907412]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
SkilledJunior
Member

Откуда:
Сообщений: 303
Alibek B.
Я как раз и думал заменить два сравнения на один full join, но не получилось.
Или это принципиально не получиться сделать за раз?

Элементарно.
+
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
13 июн 19, 23:25    [21908270]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
-2-
Member

Откуда:
Сообщений: 14844
SkilledJunior
Элементарно.
Демонстрация абстрактного синтаксиса full join есть в документации, а предметного в исходном сообщении темы.
14 июн 19, 06:47    [21908311]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
SkilledJunior
Member

Откуда:
Сообщений: 303
-2-,

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

+
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)
14 июн 19, 22:52    [21909017]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Alibek B.
Member

Откуда:
Сообщений: 3189
Tesamid
вот примерное решение задачи, если нужны какие-то реквизиты тарифов или клиентов, то просто джойним в нужных местах.

Да, истина где-то рядом, но критерии сравнения для запроса у меня не получается придумать.
Наверное буду решать построчным анализом на клиенте.

SkilledJunior
Элементарно.

Не вижу принципиальных отличий от того, что я написал в самом начале.
17 июн 19, 14:18    [21909776]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
SQL*Plus
Member

Откуда: Россия, Москва
Сообщений: 7880
Alibek B.
Tesamid
вот примерное решение задачи, если нужны какие-то реквизиты тарифов или клиентов, то просто джойним в нужных местах.

Да, истина где-то рядом, но критерии сравнения для запроса у меня не получается придумать.
Наверное буду решать построчным анализом на клиенте.
Даже это лучше делать на сервере:
не будет сетевых задержек и дополнительной нагрузки на сеть.
17 июн 19, 14:48    [21909811]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Alibek B.
Member

Откуда:
Сообщений: 3189
Да, возможно и так.
17 июн 19, 15:19    [21909868]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 547
Alibek B.
Наверное это типичная задача на сравнение двух наборов.
Скорее это типичная задача на outer join partition by.

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

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

Вероятно, ты предварительно еще захочешь сделать проверку на число пакетов на клиента, но я, думаю, справишься.
17 июн 19, 18:12    [21910114]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 547
Кобанчег
Скорее это типичная задача на outer join partition by.
Принимая во внимание особенности задания иерархии надо добавить строки для "корней" привязанные к null, чтоб client 2 не пропадал.
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.
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
17 июн 19, 19:05    [21910138]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 547
Кобанчег
when max(cnt_parent) > 1 then 'more than one bundle: '
17 июн 19, 19:09    [21910140]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Alibek B.
Member

Откуда:
Сообщений: 3189
Спасибо, завтра поэкспериментирую.
17 июн 19, 20:42    [21910178]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
SkilledJunior
Member

Откуда:
Сообщений: 303
SkilledJunior
Не вижу принципиальных отличий от того, что я написал в самом начале.

Если соберешь эталон соответствующим образом, тогда сможешь сравнивать, а так у тебя факт имеет одну структуру, эталон другую.

Здесь пример, какой эталон ты должен был собрать на представленный тобой факт 21909017
17 июн 19, 22:29    [21910196]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 547
Шож ты тычешь свой full join по поводу и без, юное бездарование.
Господину Алибеку не надо проверять на наличие несуществующих услуг, ему надо найти криво оформлнные пакеты услуг.
Перед рассуждениями про сферические эталоны в вакууме попытайся еще раз осилить постановку.
17 июн 19, 23:00    [21910205]     Ответить | Цитировать Сообщить модератору
 Re: Подскажите, как правильно сравнивать между собой два набора данных  [new]
SkilledJunior
Member

Откуда:
Сообщений: 303
Кобанчег
Шож ты тычешь свой full join по поводу и без, юное бездарование.
Господину Алибеку не надо проверять на наличие несуществующих услуг, ему надо найти криво оформлнные пакеты услуг.
Перед рассуждениями про сферические эталоны в вакууме попытайся еще раз осилить постановку.

Смешные вы, ну мастерите дальше ...
17 июн 19, 23:29    [21910215]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить