powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Самый популярное ( с весами ) значение атрибута
3 сообщений из 3, страница 1 из 1
Самый популярное ( с весами ) значение атрибута
    #39297206
Valergrad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть табличка, в которое есть поля code - код товара, скажем ( первичный ключ ) , part - некий разрез, quantity - количество товара, и куча полей атрибутов. Для примера создадим табличку с тремя атрибутами:
Код: plsql
1.
create table test1 ( part number, code number, quantity number, attr1 varchar2(100), attr2 varchar2(100), attr3 varchar2(100) );


Заполним например такими данными:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
insert into test1 values ( 1,  1, 3, 'a', 'a', 'a');
insert into test1 values ( 1,  2, 4, 'a', 'b', 'b');
insert into test1 values ( 1,  3, 5, 'b', 'b', 'c');
insert into test1 values ( 1,  4, 100, null, null, null);
insert into test1 values ( 2,  5, 0, 'a', 'b', 'c');
insert into test1 values ( 2,  6, 1, 'a', 'a', 'b');
insert into test1 values ( 2,  7, 2, 'b', 'b', 'a');
insert into test1 values ( 2,  8, null, 'a', 'b', 'c');
commit;


Необходимо для каждой части из part найти самое популярное значение каждого атрибута с учетом количества.
Скажем, для part = 1 и атрибута attr1 у нас два возможных значения - 'a' и 'b' . Для 'a' - суммарное количество 7 ( 3+4), для 'b' - 5. Стало быть самый популярное значение attr1 в данном разрезе - 'a'. А вот у attr2 значение 'b' дает сумму 9 ( 4+5) и поэтому самое популярное. Атрибут null не может быть самым популярным ( в таком случае нужно вывести второй по популярности ).
Т.е. правильный ответ для таких данных будет выглядеть вот так:

"PART";"ATTR1";"ATTR2";"ATTR3""1";"a";"b";"c""2";"b";"b";"a"

Принимаются ваши идеи как это сделать. Сейчас это выглядит как вот такая жесть:

Код: 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.
select part,
       max((select inn.attr
           from (select row_number() over(order by decode(test1.attr1, null, 0, 1) desc, sum(test1.quantity) desc) rn,
                        test1.attr1 attr
                 from test1
                 where test1.part = t.part
                 group by test1.attr1) inn
           where inn.rn = 1)) attr1,
       max((select inn.attr
           from (select row_number() over(order by decode(test1.attr2, null, 0, 1) desc, sum(test1.quantity) desc) rn,
                        test1.attr2 attr
                 from test1
                 where test1.part = t.part
                 group by test1.attr2) inn
           where inn.rn = 1)) attr2,
       max((select inn.attr
           from (select row_number() over(order by decode(test1.attr3, null, 0, 1) desc, sum(test1.quantity) desc) rn,
                        test1.attr3 attr
                 from test1
                 where test1.part = t.part
                 group by test1.attr3) inn
           where inn.rn = 1)) attr3
from test1 t
group by part ;





Выглядит ужасно и работает медленно ( в таблице может быть до 10 000 строк, атрибутов около 50). Думаю переделать на вот такое:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
with inn as
 (select code,
         part,
         attr1,
         nvl2 ( attr1 , sum(test1.quantity) over(partition by part, attr1) , -1) q1,
         attr2,
         nvl2 ( attr1 , sum(test1.quantity) over(partition by part, attr2) , -1) q2,
         attr3,
         nvl2 ( attr1 , sum(test1.quantity) over(partition by part, attr3) , -1) q3
  from test1)
select part, max(attr1) keep ( dense_rank first order by q1 desc ) attr1,
max(attr2) keep ( dense_rank first order by q2 desc ) attr2,
max(attr3) keep ( dense_rank first order by q3 desc ) attr3
from inn
group by part;



Но возможно кто-то предложит совсем красивый вариант без подзапросов, вдруг есть какой-то хитрый трюк.
...
Рейтинг: 0 / 0
Самый популярное ( с весами ) значение атрибута
    #39297228
Глупый Телевизор
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Valergrad,

unpivot + group by
...
Рейтинг: 0 / 0
Самый популярное ( с весами ) значение атрибута
    #39297814
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select part
     , max(ax1) a1 
     , max(ax2) a2 
     , max(ax3) a3
from(
select t.part, attr1, attr2, attr3
     , sum(t.quantity) amt
     , first_value(attr1 ignore nulls) over(partition by part order by sum(t.quantity) desc) ax1
     , first_value(attr2 ignore nulls) over(partition by part order by sum(t.quantity) desc) ax2
     , first_value(attr3 ignore nulls) over(partition by part order by sum(t.quantity) desc) ax3
  from test1 t
 group by grouping sets((t.part, t.attr1), (t.part, t.attr2), (t.part, t.attr3)) 
) group by part
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Самый популярное ( с весами ) значение атрибута
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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