Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Суммирование с условием / 25 сообщений из 27, страница 1 из 2
27.03.2020, 18:48
    #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
28.03.2020, 06:32
    #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
28.03.2020, 07:52
    #39941823
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
artas
если записей больше 10
если категорий ровно 10
Код: plsql
1.
group by name

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

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


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

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

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

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

artas
+ не решил, если категорий ровно 10, то не выводить Other
...
Рейтинг: 0 / 0
28.03.2020, 13:53
    #39941866
PuM256
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
Тьфу блин, ночью писал, неправильно условие понял. Думал, собирать всё в Others, если записей больше 10
...
Рейтинг: 0 / 0
28.03.2020, 23:35
    #39941930
-2-
-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
29.03.2020, 03:09
    #39941946
SY
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
30.03.2020, 11:30
    #39942183
artas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
-2-,

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

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

Как дополнить define, я указывал в стертом ответе.
...
Рейтинг: 0 / 0
30.03.2020, 15:00
    #39942264
SY
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
30.03.2020, 15:12
    #39942271
artas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
SY
Кстати, sum(a) там по-барабану

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

-2-,SY, спасибо, сейчас попробую
...
Рейтинг: 0 / 0
30.03.2020, 15:25
    #39942274
SY
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
30.03.2020, 15:33
    #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
30.03.2020, 15:38
    #39942281
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
Еще раз. Просто сделай подзапрос с изначальными данными отсортирован по % (поле а) запросом и дотачай к нему fetch first 9 rows only.

SY.
...
Рейтинг: 0 / 0
31.03.2020, 09:03
    #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
31.03.2020, 09:14
    #39942428
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
Stax
чем row_number() не подходит?
Вряд ли row_number можно считать более изящным, чем rownum и уж точно только замены шила на мыло не достаточно для пожелания десяти именованных категорий.
...
Рейтинг: 0 / 0
31.03.2020, 10:14
    #39942454
artas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
Stax,

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

т.к. на 10 записях последнюю переименовывает в others
...
Рейтинг: 0 / 0
31.03.2020, 10:36
    #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
31.03.2020, 11:22
    #39942479
artas
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Суммирование с условием
Stax,

спасибо, общий каунт первое что пришло в голову, но это уж очень влоб. Ладно, буду выполнять на клиенте. Всем спасибо, тему можно закрывать
...
Рейтинг: 0 / 0
31.03.2020, 12:17
    #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
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Суммирование с условием / 25 сообщений из 27, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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