powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / выбрать лучший из трех вариантов
10 сообщений из 10, страница 1 из 1
выбрать лучший из трех вариантов
    #39487303
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть таблица-источник мусорных данных (в примере ниже - dat ), в которой в одной строке содержится 3 (три!) идентификатора адреса
есть не менее мусорный справочник адресов (regions ), в котором некоторые адреса заполнены полностью, некоторые - с пропусками полей

задача - соединив таблицы, найти для каждой из строк данных самый заполненный адрес - и вернуть его ID (result_needed в примере ниже)

вопрос - как это сделать красиво (без большой многоэтажности и хранимых функций)

пример:
Код: 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 regions as (
select 3 r, 'Московская' region, 'Чеховский' subregion, 'Чехов' city from dual union all
select 2 r, 'Московская' region, 'Чеховский' subregion, null city from dual union all
select 1 r, 'Московская' region, null subregion, null city from dual union all
select 6 r, 'Ленинградская' region, 'Выборгский' subregion, 'Выборг' city from dual union all
select 5 r, 'Ленинградская' region, 'Выборгский' subregion, null city from dual union all
select 4 r, 'Ленинградская' region, null subregion, null city from dual 
),
dat as (
select 1 r,1 s,1 c, 1 result_needed from dual union all
select 1 r,1 s,2 c, 2 result_needed from dual union all
select 1 r,2 s,2 c, 2 result_needed  from dual union all
select 2 r,2 s,2 c, 2 result_needed  from dual union all
select 1 r,2 s,3 c, 3 result_needed  from dual union all
select 4 r,4 s,4 c, 4 result_needed  from dual union all
select 4 r,5 s,6 c, 6 result_needed  from dual union all
select 4 r,5 s,5 c, 5 result_needed  from dual union all
select 5 r,5 s,6 c, 6 result_needed  from dual union all
select 3 r,4 s,6 c, 3 result_needed  from dual --здесь подходят под условие и id=3, и 6 - выбираем первый самый длинный адрес по порядку следования полей (r,s,c)
)
select *
from dat
inner join regions r1 on dat.r=r1.r
inner join regions r2 on dat.s=r2.r
inner join regions r3 on dat.c=r3.r


спасибо!
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487323
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexus12
Код: plsql
1.
выбираем первый

"Первость" не раскрыта.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
 21  select d.*
 22       , (select min(r.r) keep (dense_rank first order by r.city, r.subregion, r.region)
 23            from regions r
 24            where r.r in (d.r, d.s, d.c)
 25         ) as rr
 26    from dat d
 27  ;

         R          S          C RESULT_NEEDED         RR
---------- ---------- ---------- ------------- ----------
         1          1          1             1          1
         1          1          2             2          2
         1          2          2             2          2
         2          2          2             2          2
         1          2          3             3          3
         4          4          4             4          4
         4          5          6             6          6
         4          5          5             5          5
         5          5          6             6          6
         3          4          6             3          6

...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487331
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexus12,

Ты бы пример желаемого результата привел, не все люди обладают телепатическими способностями, чтобы домыслить это по твоей недопостановке задачи.
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487340
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKadпример желаемого результатаAlexus12
Код: plsql
1.
result_needed
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487371
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,

спасибо, решение красивое!

вопрос в масштабируемости - что будет на гигантских справочниках (100 тыс+ строк в REGIONS)?
подзапрос же хочет nested loops для каждой строки данных? возможен ли вариант через HASH\FTS?
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487530
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexus12вопрос в масштабируемости - что будет на гигантских справочниках (100 тыс+ строк в REGIONS)?
подзапрос же хочет nested loops для каждой строки данных? возможен ли вариант через HASH\FTS?
На серьезных системах возможен и желателен вариант предварительно очистки данных.
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487586
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,
к сожалению, это аналитическая задача (поиск алмазов среди имеющегося в двх мусора)

есть решение через hash\fts?

в лоб напрашивается такой алгоритм над запросом из первого поста (где будет как раз FTS\HASH):

1) добавить три вычисляемых поля: "CASE WHEN проверяем поля 1...3 справочника на null then вернуть рейтинг заполненности справочника" - получаем три поля (по одному на справочник) со значениями весов от 0 (все пусто) до 3 (все заполнено), например
0, 2, 1

2) вычисляем greatest из трех полей п.1 - получаем максимальное значение рейтинга среди трех вычисленных
= 2

3) теперь нужно получить ID записи справочника, соответствующий найденному greatest весу.
опять case - when (результат greatest) = весу справочника 1 then id_справ_1, ELSE сверим со вторым и тд....


есть решение красивее?
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487768
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
реализация по алгоритму из поста выше

Код: 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 regions as (--справочник
select 30 r, 'Московская' region, 'Чеховский' subregion, 'Чехов' city from dual union all select 20 r, 'Московская' region, 'Чеховский' subregion, null city from dual union all select 10 r, 'Московская' region, null subregion, null city from dual union all select 60 r, 'Ленинградская' region, 'Выборгский' subregion, 'Выборг' city from dual union all select 50 r, 'Ленинградская' region, 'Выборгский' subregion, null city from dual union all select 40 r, 'Ленинградская' region, null subregion, null city from dual union all select 70 r, null region, 'sss' subregion, null city from dual ), 
regions_q as 
( select regions.*, --вес (качество) заполнения справочника 
case when region is not null and subregion is not null and city is not null then 3
     when region is not null and subregion is not null and city is     null then 2
     when region is not null and subregion is     null and city is     null then 1
     else 0
end as reg_quality     
from regions)
,dat as (--факты
select 10 r,10 s,10 c, 10 result_needed from dual union all select 10 r,10 s,20 c, 20 result_needed from dual union all select 10 r,20 s,20 c, 20 result_needed  from dual union all select 20 r,20 s,20 c, 20 result_needed  from dual union all select 10 r,20 s,30 c, 30 result_needed  from dual union all select 40 r,40 s,40 c, 40 result_needed  from dual union all select 40 r,50 s,60 c, 60 result_needed  from dual union all select 40 r,50 s,50 c, 50 result_needed  from dual union all select 50 r,50 s,60 c, 60 result_needed  from dual union all select 30 r,40 s,60 c, 30 result_needed  from dual --здесь подходят под условие и id=30, и 60 - выбираем первый самый длинный адрес по порядку следования полей (r,s,c)
)
, dat2 as (
select dat.*,
r1.r id1, r1.region region1, r1.subregion subregion1, r1.city city1, r1.reg_quality reg_quality1, r2.r id2,r2.region region2, r2.subregion subregion2, r2.city city2, r2.reg_quality reg_quality2, r3.r id3,r3.region region3, r3.subregion subregion3, r3.city city3, r3.reg_quality reg_quality3,
 --наилучший заполненный из трех 
greatest(r1.reg_quality, r2.reg_quality, r3.reg_quality) best_quality 
from dat inner join regions_q r1 on dat.r=r1.r inner join regions_q r2 on dat.s=r2.r inner join regions_q r3 on dat.c=r3.r
)
select dat2.* ,
--вернуть id справочника с best_quality
case when best_quality = reg_quality1 then id1
     when best_quality = reg_quality2 then id2
     when best_quality = reg_quality3 then id3 end as best_id from dat2



есть решение красивее?
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39487779
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexus12есть решение красивее?Тупо, как валенок:
Код: 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.
 21  select d.*
 22       , case when c.city      is not null then c.r
 23              when s.city      is not null then s.r
 24              when r.city      is not null then r.r
 25              when c.subregion is not null then c.r
 26              when s.subregion is not null then s.r
 27              when r.subregion is not null then r.r
 28              when c.region    is not null then c.r
 29              when s.region    is not null then s.r
 30              when r.region    is not null then r.r
 31         end as rr
 32    from dat d
 33      join regions r on d.r=r.r
 34        join regions s on d.s=s.r
 35          join regions c on d.c=c.r
 36  ;

         R          S          C RESULT_NEEDED         RR
---------- ---------- ---------- ------------- ----------
         1          2          3             3          3
         1          1          2             2          2
         1          2          2             2          2
         2          2          2             2          2
         1          1          1             1          1
         3          4          6             3          6
         4          5          6             6          6
         5          5          6             6          6
         4          5          5             5          5
         4          4          4             4          4
...
Рейтинг: 0 / 0
выбрать лучший из трех вариантов
    #39489051
Alexus12
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,
спасибо, действительно просто!
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / выбрать лучший из трех вариантов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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