powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Суммирование с условием
25 сообщений из 27, страница 1 из 2
Суммирование с условием
    #39941768
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток. Подскажите пожалуйста, есть ли более элегантный способ, чем мой
Требуется если записей больше 10, остальные суммировать в категорию Others. В принципе сделал, но чет мне кажется что есть более изящное решение + не решил, если категорий ровно 10, то не выводить Other
Предполагается что основной подзапрос отсортирован по a desc
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
select name,sum(perc) from (
select case when rownum > 9 then 'Other' else name end as name,a as perc from (
select 0.1 as a, 'a' as name from dual union all
select 0.1 as a, 'b' as name from dual union all
select 0.1 as a, 'c' as name from dual union all
select 0.1 as a, 'd' as name from dual union all
select 0.1 as a, 'e' as name from dual union all
select 0.1 as a, 'f' as name from dual union all
select 0.1 as a, 'g' as name from dual union all
select 0.1 as a, 'h' as name from dual union all
select 0.1 as a, 'q' as name from dual union all
select 0.05 as a, 'o' as name from dual union all
select 0.05 as a, 'p' as name from dual
)
) group by name
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941821
PuM256
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
artas,

На счёт изящности не уверен, но если хочется по-другому, то можно так:

Код: plsql
1.
2.
3.
4.
5.
6.
Select Nvl(Name, 'Other') name, perc From (
  Select Name, Sum(a) perc, Count(Name) over() totalcnt From t
  Group By Rollup(Name))
Where
  (totalcnt < 10 And Name Is Not Null)
  Or (totalcnt > 10 And Name Is Null);
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941823
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
если записей больше 10
если категорий ровно 10
Код: plsql
1.
group by name

Ты уж определись, что ты собрался считать: записи или группы.
artas
основной подзапрос отсортирован по a desc
Случайным образом (из-за недетерминированного порядка) относить что-либо в "прочее" отсечкой по случайному номеру - это неадекватность, как минимум, постановщика.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941824
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PuM256
но если хочется по-другому, то можно так:
Чудак, а то, что результат не то что не совпадает, а вовсе отсутствует, не смущает? Почему не просто select * from dual ?
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941831
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic
artas
если записей больше 10
если категорий ровно 10
Код: plsql
1.
group by name

Ты уж определись, что ты собрался считать: записи или группы.
artas
основной подзапрос отсортирован по a desc
Случайным образом (из-за недетерминированного порядка) относить что-либо в "прочее" отсечкой по случайному номеру - это неадекватность, как минимум, постановщика.


Имена груп уникальны, так что считаются записи, кроме случая Other

Понятно что итоговый запрос собьет сортировку, о это не страшно, главное что Other проставит наименьшим значениям.

Это данные для круговой диаграммы если что
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941839
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
Код: plsql
1.
rownum

RTFM row_number()
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941865
PuM256
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic,

artas
+ не решил, если категорий ровно 10, то не выводить Other
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941866
PuM256
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тьфу блин, ночью писал, неправильно условие понял. Думал, собирать всё в Others, если записей больше 10
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941930
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select *
from t match_recognize (
  order by name
  measures classifier() as class, match_number() as mnum, first(name) as name, sum(a) as a
  pattern (f1 | others*)
  define f1 as match_number() < 10
);
...
Рейтинг: 0 / 0
Суммирование с условием
    #39941946
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-
Код: plsql
1.
2.
3.
4.
5.
6.
7.
select *
from t match_recognize (
  order by name
  measures classifier() as class, match_number() as mnum, first(name) as name, sum(a) as a
  pattern (f1 | others*)
  define f1 as match_number() < 10
);



artas

Предполагается что основной подзапрос отсортирован по a desc


SY.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942183
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-,

спасибо, не знал про match_recognize

Как я понимаю, решения для "если записей ровно 10, то не выводить others" красивого нету ?
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942256
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
не знал про match_recognize


Ты определился: первые 9 из отсортированых по a desc или ервые 9 из отсортированых по name. Если по name и не выводить others"
то в данном случае (define f1 as match_number() < 10) банально убираешь pattern others.

Код: 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.
with t as (
           select 0.1 as a, 'a' as name from dual union all
           select 0.1 as a, 'b' as name from dual union all
           select 0.1 as a, 'c' as name from dual union all
           select 0.1 as a, 'd' as name from dual union all
           select 0.1 as a, 'e' as name from dual union all
           select 0.1 as a, 'f' as name from dual union all
           select 0.1 as a, 'g' as name from dual union all
           select 0.1 as a, 'h' as name from dual union all
           select 0.1 as a, 'q' as name from dual union all
           select 0.05 as a, 'o' as name from dual union all
           select 0.05 as a, 'p' as name from dual
          )
select *
from t match_recognize (
  order by name
  measures classifier() as class, match_number() as mnum, first(name) as name, sum(a) as a
  pattern (f1)
  define f1 as match_number() < 10
)
/

CLASS        MNUM N          A
------ ---------- - ----------
F1              1 a         .1
F1              2 b         .1
F1              3 c         .1
F1              4 d         .1
F1              5 e         .1
F1              6 f         .1
F1              7 g         .1
F1              8 h         .1
F1              9 o        .05

9 rows selected.

SQL>



SY.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942262
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
Как я понимаю, решения для "если записей ровно 10, то не выводить others" красивого нету ?
№2. Ты понимаешь неправильно.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942263
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
Ты определился: первые 9 из отсортированых по a desc или ервые 9 из отсортированых по name.
Если обратить внимание на "Это данные для круговой диаграммы если что", то несложно перефразировать автора до тезисов:
- если входных записей 10 и меньше, выходные соответствуют входным.
- если больше, выводятся 9 входных, входная 10 и далее агрегируются в одну выходную 10 other.

Как дополнить define, я указывал в стертом ответе.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942264
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, sum(a) там по-барабану. Это решение ничего не суммирует, т.к. в pattern всего одна строка:

Код: 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.
with t as (
           select 0.1 as a, 'a' as name from dual union all
           select 0.1 as a, 'b' as name from dual union all
           select 0.1 as a, 'c' as name from dual union all
           select 0.1 as a, 'c' as name from dual union all
           select 0.1 as a, 'e' as name from dual union all
           select 0.1 as a, 'f' as name from dual union all
           select 0.1 as a, 'g' as name from dual union all
           select 0.1 as a, 'h' as name from dual union all
           select 0.1 as a, 'q' as name from dual union all
           select 0.05 as a, 'o' as name from dual union all
           select 0.05 as a, 'p' as name from dual
          )
select *
from t match_recognize (
  order by name
  measures classifier() as class, match_number() as mnum, first(name) as name, sum(a) as a
  pattern (f1)
  define f1 as match_number() < 10
)
/

CLASS        MNUM N          A
------ ---------- - ----------
F1              1 a         .1
F1              2 b         .1
F1              3 c         .1
F1              4 c         .1
F1              5 e         .1
F1              6 f         .1
F1              7 g         .1
F1              8 h         .1
F1              9 o        .05

9 rows selected.

SQL>



SY.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942271
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
Кстати, sum(a) там по-барабану

да, вы правы, сум ничего и не должно суммировать, тк названия уникальны (разве что у меня в примере было по other), это было нужно для группировки.

-2-,SY, спасибо, сейчас попробую
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942274
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
SY
Кстати, sum(a) там по-барабану

да, вы правы, сум ничего и не должно суммировать, тк названия уникальны (разве что у меня в примере было по other), это было нужно для группировки.

-2-,SY, спасибо, сейчас попробую


??? Тогда зачем в исходнике у тебя group by name если name уникальны? Т.e. все что нужно это первые 9 строк отсортированых по a desc:

Код: 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.
with t as (
           select 0.1 as a, 'a' as name from dual union all
           select 0.1 as a, 'b' as name from dual union all
           select 0.1 as a, 'c' as name from dual union all
           select 0.1 as a, 'd' as name from dual union all
           select 0.1 as a, 'e' as name from dual union all
           select 0.1 as a, 'f' as name from dual union all
           select 0.1 as a, 'g' as name from dual union all
           select 0.1 as a, 'h' as name from dual union all
           select 0.1 as a, 'q' as name from dual union all
           select 0.05 as a, 'o' as name from dual union all
           select 0.05 as a, 'p' as name from dual
          )
select  *
  from  t
  order by a desc
  fetch first 9 rows only
/

         A N
---------- -
        .1 a
        .1 b
        .1 c
        .1 d
        .1 e
        .1 f
        .1 g
        .1 h
        .1 q

9 rows selected.

SQL>



Или по name:

Код: 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.
with t as (
           select 0.1 as a, 'a' as name from dual union all
           select 0.1 as a, 'b' as name from dual union all
           select 0.1 as a, 'c' as name from dual union all
           select 0.1 as a, 'd' as name from dual union all
           select 0.1 as a, 'e' as name from dual union all
           select 0.1 as a, 'f' as name from dual union all
           select 0.1 as a, 'g' as name from dual union all
           select 0.1 as a, 'h' as name from dual union all
           select 0.1 as a, 'q' as name from dual union all
           select 0.05 as a, 'o' as name from dual union all
           select 0.05 as a, 'p' as name from dual
          )
select  *
  from  t
  order by name
  fetch first 9 rows only
/

         A N
---------- -
        .1 a
        .1 b
        .1 c
        .1 d
        .1 e
        .1 f
        .1 g
        .1 h
       .05 o

9 rows selected.

SQL>



SY.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942277
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
artas
не знал про match_recognize


Ты определился: первые 9 из отсортированых по a desc или ервые 9 из отсортированых по name. Если по name и не выводить others"
то в данном случае (define f1 as match_number() < 10) банально убираешь pattern others.


подзапрос с изначальными данными отсортирован по % (поле а)
name - уникально для каждой строки
цель - из данной выборки, получить
9 записей неизменных, отсортированныйх по полю а, по убыванию
+ остальное суммированное под общим именем Other
либо, если записей 10 илил меньше, получить изначальный набор

для приведенного варианта это

0.1 a
0.1 b
0.1 c
0.1 d
0.1 e
0.1 f
0.1 g
0.1 h
0.1 q
0.1 Other
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942281
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще раз. Просто сделай подзапрос с изначальными данными отсортирован по % (поле а) запросом и дотачай к нему fetch first 9 rows only.

SY.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942424
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas,

чем row_number() не подходит? или принципиально c match_recognize?
Код: 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.
  1  with t as (
  2             select 0.1 as a, 'a' as name from dual union all
  3             select 0.1 as a, 'b' as name from dual union all
  4             select 0.1 as a, 'c' as name from dual union all
  5             select 0.1 as a, 'd' as name from dual union all
  6             select 0.1 as a, 'e' as name from dual union all
  7             select 0.1 as a, 'f' as name from dual union all
  8             select 0.1 as a, 'g' as name from dual union all
  9             select 0.1 as a, 'h' as name from dual union all
 10             select 0.1 as a, 'q' as name from dual union all
 11             select 0.05 as a, 'o' as name from dual union all
 12             select 0.05 as a, 'p' as name from dual
 13            )
 14  ,tt as (select t.*, row_number() over (order by name /*desc*/) rn from t)
 15  select
 16     decode(decode(greatest(rn,9),9,rn,1E62),1e62,'Others',max(name)) name
 17     ,sum(a) a
 18  from tt
 19  group by decode(greatest(rn,9),9,rn,1E62)
 20* order by decode(greatest(rn,9),9,rn,1E62)
SQL> /

NAME            A
------ ----------
a              .1
b              .1
c              .1
d              .1
e              .1
f              .1
g              .1
h              .1
o             .05
Others        .15

10 rows selected.



......
stax
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942428
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
чем row_number() не подходит?
Вряд ли row_number можно считать более изящным, чем rownum и уж точно только замены шила на мыло не достаточно для пожелания десяти именованных категорий.
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942454
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

спасибо, отличный вариант, возможно ли сдесь сделать
если записей ровно 10(в подзапросе) то оставлять выборку без изменений ?

т.к. на 10 записях последнюю переименовывает в others
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942463
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
Stax,
т.к. на 10 записях последнюю переименовывает в others


решение влоб (мне не нравится)
Код: 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.
SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2             select 0.1 as a, 'a' as name from dual union all
  3             select 0.1 as a, 'b' as name from dual union all
  4             select 0.1 as a, 'c' as name from dual union all
  5             select 0.1 as a, 'd' as name from dual union all
  6             select 0.1 as a, 'e' as name from dual union all
  7             select 0.1 as a, 'f' as name from dual union all
  8             select 0.1 as a, 'g' as name from dual union all
  9             select 0.1 as a, 'h' as name from dual union all
 10             select 0.1 as a, 'q' as name from dual union all
 11  --           select 0.05 as a, 'o' as name from dual union all
 12             select 0.05 as a, 'p' as name from dual
 13            )
 14  ,tt as (
 15   select
 16    t.*
 17   ,row_number() over (order by name /*desc*/) rn
 18   ,count(*) over () cc
 19  from t
 20  )
 21  select
 22      decode(decode(greatest(rn,9),9,rn,decode(cc,10,rn,1E62)),1e62,'Others',max(name)) name
 23     ,sum(a) a
 24  from tt
 25  group by decode(greatest(rn,9),9,rn,decode(cc,10,rn,1E62))
 26* order by decode(greatest(rn,9),9,rn,decode(cc,10,rn,1E62))
SQL> /

NAME            A
------ ----------
a              .1
b              .1
c              .1
d              .1
e              .1
f              .1
g              .1
h              .1
p             .05
q              .1

10 rows selected.



....
stax
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942479
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

спасибо, общий каунт первое что пришло в голову, но это уж очень влоб. Ладно, буду выполнять на клиенте. Всем спасибо, тему можно закрывать
...
Рейтинг: 0 / 0
Суммирование с условием
    #39942500
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
artas
Stax,

спасибо, общий каунт первое что пришло в голову, но это уж очень влоб. Ладно, буду выполнять на клиенте. Всем спасибо, тему можно закрывать


без каунт (но всеравно не красиво)
Код: 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.
SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2             select 0.1 as a, 'a' as name from dual union all
  3             select 0.1 as a, 'b' as name from dual union all
  4             select 0.1 as a, 'c' as name from dual union all
  5             select 0.1 as a, 'd' as name from dual union all
  6             select 0.1 as a, 'e' as name from dual union all
  7             select 0.1 as a, 'f' as name from dual union all
  8             select 0.1 as a, 'g' as name from dual union all
  9             select 0.1 as a, 'h' as name from dual union all
 10             select 0.1 as a, 'q' as name from dual union all
 11  --           select 0.05 as a, 'o' as name from dual union all
 12             select 0.05 as a, 'p' as name from dual
 13            )
 14  ,tt as (
 15   select
 16    t.*
 17    ,lag(name,9) over (order by name) lg9
 18    ,lag(name,10) over (order by name) lg10
 19    ,lead(name) over (order by name) le
 20  from t
 21  )
 22  select
 23      decode(lg9,null,name,decode(lg10||le,null,name,'Others')) n
 24     ,sum(a) a
 25  from tt
 26  group by decode(lg9,null,name,decode(lg10||le,null,name,'Others'))
 27* order by decode(n,'Others',2,1),n
SQL> /

N               A
------ ----------
a              .1
b              .1
c              .1
d              .1
e              .1
f              .1
g              .1
h              .1
p             .05
q              .1

10 rows selected.

SQL>



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


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