powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Агрегация сумм в иерархических запросах
13 сообщений из 63, страница 3 из 3
Агрегация сумм в иерархических запросах
    #37726364
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ПЕНСИОНЕРКАпредпочитала подготовить полуфабрикат
--итоги по цех,участок,профессия,месяц, наименование итога, сумма во временную таблицу РАБ1

ну, это по задаче
где-то надо, где-то и не нужно, где-то вообще не имеет смысла, а где-то через WITH
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #37832509
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Еще вариант. Как-то так получилось. Правда на больших обьемах данных не тестировал
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
select v, p, sum(am2) am from (
select v,p, level, xx_sql.query('select '||sys_connect_by_path('('||to_char(am)||')','+')||' from dual') am2 
from (
select 1 v , 0 p, 0 am from dual
union all
select 2 v, 1 p, 120.2 am from dual
union all
select 4 v, 2 p, -75 am from dual
union all
select 5 v, 2 p, 23 am from dual
union all
select 3 v, 1 p, 210 am from dual  
) t
connect by v = prior p
--start with p = 0 -- не указываем откуда собираем
) group by v,p


функция xx_sql.query возвращает результат первой колонки первой строки указанного запроса. можно заменить на что попроще.
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #37836285
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82Еще вариант. Как-то так получилось. Правда на больших обьемах данных не тестировал
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
select v, p, sum(am2) am from (
select v,p, level, xx_sql.query('select '||sys_connect_by_path('('||to_char(am)||')','+')||' from dual') am2 
from (
select 1 v , 0 p, 0 am from dual
union all
select 2 v, 1 p, 120.2 am from dual
union all
select 4 v, 2 p, -75 am from dual
union all
select 5 v, 2 p, 23 am from dual
union all
select 3 v, 1 p, 210 am from dual  
) t
connect by v = prior p
--start with p = 0 -- не указываем откуда собираем
) group by v,p


функция xx_sql.query возвращает результат первой колонки первой строки указанного запроса. можно заменить на что попроще.Не совсем понятна затея строить всё из всех, чтоб потом тупо схлопнуть, но в своей функции здесь нет особой необходимости.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
select v, p, 
       xmlcast(xmlquery(max(sys_connect_by_path(am,'+')) returning content) as number) result,
       max(sys_connect_by_path(am,'+')) str
from (
select 1 v , 0 p, 0 am from dual
union all
select 2 v, 1 p, 120.2 am from dual
union all
select 4 v, 2 p, -75 am from dual
union all
select 5 v, 2 p, 23 am from dual
union all
select 3 v, 1 p, 210 am from dual  
) t
connect by v = prior p
--start with p = 0
group by v,p
order by 1
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #37836305
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chameleon82,

Впрочем, и тебе и мне можно было предварительно сделать поиск и найти примерно это .
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #37836339
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как минимум надо не забывать, что макс длина результата sys_connect_by_path = 4000
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #38000032
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Чуть выше ошибочка была. Для Oracle >= 11.2.0.2, правда с ограничением
andreymxкак минимум надо не забывать, что макс длина результата sys_connect_by_path = 4000
возможен такой код
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
select id, parent_id
, max(level)
, xmlcast(xmlquery( listagg( sys_connect_by_path(s,'+')
          ) WITHIN GROUP (ORDER BY null)
          returning content) as number)
           amount
 from (
select 1 id, null parent_id, 0 s from dual
union all
select 2 id, 1 parent_id, 0 s from dual
union all
select 3 id, 1 parent_id, 0 s from dual
union all
select 4 id, 2 parent_id, 20 s from dual
union all
select 5 id, 2 parent_id, 50 s from dual
union all
select 6 id, 3 parent_id, 40 s from dual
union all
select 7 id, 3 parent_id, 10 s from dual
) t 
connect by prior parent_id =  id
group by id,parent_id 



и опять же на 11-ом, но уже цивилизованный обход
Код: 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.
WITH
  tbl AS ( select 1 id, null parent_id, 0 s from dual
              union all
              select 2 id, 1 parent_id, 0 s from dual
              union all
              select 3 id, 1 parent_id, 0 s from dual
              union all
              select 4 id, 2 parent_id, 20 s from dual
              union all
              select 5 id, 2 parent_id, 50 s from dual
              union all
              select 6 id, 3 parent_id, 40 s from dual
              union all
              select 7 id, 3 parent_id, 10 s from dual
),   
  hier (id, parent_id, amount, lvl) AS
  (
select t.id, t.parent_id, t.s, 0 lvl 
from tbl t
union all
select t.id, t.parent_id, nvl(t.s,0) + nvl(c.amount,0), c.lvl+1 
from tbl t inner join hier c on (t.id = c.parent_id)
  )
SEARCH DEPTH FIRST BY id SET order1
SELECT id , parent_id, sum(amount), max(lvl) mgrLevel, max(order1) ord
FROM hier
GROUP BY id, parent_id
ORDER BY ord DESC
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Агрегация сумм в иерархических запросах
    #38468139
sim_tom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82,

все тут хорошо, до тех пор, пока не появляются родители, у которых есть свои суммы, которые надо приплюсовать к дочерним
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #38468420
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sim_tomchameleon82,

все тут хорошо, до тех пор, пока не появляются родители, у которых есть свои суммы, которые надо приплюсовать к дочерним
вас затрудняет сложить два числа ?
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #38468662
Фотография ПЕНСИОНЕРКА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sim_tom,
авторвсе тут хорошо, до тех пор, пока не появляются родители, у которых есть свои суммы, которые надо приплюсовать к дочерним

только бы это --ерунда
хуже, когда есть еще и в том числе
статьясуммапо заводу100т--по цехам 60-----в том числе основным20--по соцсфере40
по цехам всего\
по основным
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #38469341
chameleon82
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ПЕНСИОНЕРКА,

а тут что сложного?
делаете "в том числе" и "не в том числе", в конечном выводе скрываете "не в том числе". тут все в настройках иерархии, либо на ноде вообще дочерние не складывать, либо расчитывать все дочерние суммы и не расчитывать или игнорировать расчет на конкретном ноде.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Агрегация сумм в иерархических запросах
    #38871105
StayAtHome
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
chameleon82и опять же на 11-ом, но уже цивилизованный обход
Код: 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.
WITH
  tbl AS ( select 1 id, null parent_id, 0 s from dual
              union all
              select 2 id, 1 parent_id, 0 s from dual
              union all
              select 3 id, 1 parent_id, 0 s from dual
              union all
              select 4 id, 2 parent_id, 20 s from dual
              union all
              select 5 id, 2 parent_id, 50 s from dual
              union all
              select 6 id, 3 parent_id, 40 s from dual
              union all
              select 7 id, 3 parent_id, 10 s from dual
),   
  hier (id, parent_id, amount, lvl) AS
  (
select t.id, t.parent_id, t.s, 0 lvl 
from tbl t
union all
select t.id, t.parent_id, nvl(t.s,0) + nvl(c.amount,0), c.lvl+1 
from tbl t inner join hier c on (t.id = c.parent_id)
  )
SEARCH DEPTH FIRST BY id SET order1
SELECT id , parent_id, sum(amount), max(lvl) mgrLevel, max(order1) ord
FROM hier
GROUP BY id, parent_id
ORDER BY ord 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.
WITH
  tbl AS ( SELECT 1 ID, NULL parent_id, 0 s FROM dual
              UNION ALL
              SELECT 2 ID, 1 parent_id, 1 s FROM dual
              UNION ALL
              SELECT 3 ID, 1 parent_id, 0 s FROM dual
              UNION ALL
              SELECT 4 ID, 2 parent_id, 1 s FROM dual
              UNION ALL
              SELECT 5 ID, 2 parent_id, 1 s FROM dual
              UNION ALL
              SELECT 6 ID, 3 parent_id, 1 s FROM dual
              UNION ALL
              SELECT 7 ID, 3 parent_id, 1 s FROM dual
              UNION ALL
              SELECT 8 ID, 4 parent_id, 1 s FROM dual
),   
  hier (ID, parent_id, amount, lvl) AS
  (
SELECT T.ID, T.parent_id, T.s, 0 lvl 
FROM tbl T
UNION ALL
SELECT T.ID, T.parent_id, nvl(T.s,0) + nvl(c.amount,0), c.lvl+1 
FROM tbl T INNER JOIN hier c ON (T.ID = c.parent_id)
  )
SEARCH DEPTH FIRST BY ID SET order1
SELECT ID , parent_id, sum(amount), max(lvl) mgrLevel, max(order1) ord
FROM hier
GROUP BY ID, parent_id
ORDER BY ord DESC


Для простоты проверки положил s=1 для всех узлов? Пролучаю для узла 2 сумму "8" а не "4":
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
ID PARENT_ID SUM(AMOUNT) MGRLEVEL ORD
1		10	3	21
2	1	8	2	20
4	2	3	1	19
8	4	1	0	18
3	1	2	1	16
7	3	1	0	15
6	3	1	0	12
5	2	1	0	9


Никак сам не могу побороть - это вообще реально?
...
Рейтинг: 0 / 0
Агрегация сумм в иерархических запросах
    #38871142
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StayAtHomeНикак сам не могу побороть - это вообще реально?Потому что нужно поменьше ненужной фантазии, когда можно тупо в лоб
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
 19  ( select connect_by_root id as id, connect_by_root parent_id as parent_id, s
 20      from tbl
 21      connect by parent_id = prior id
 22  )
 23  select id , parent_id, sum(s) as s
 24    from hier
 25    group by id, parent_id
 26    order by id
 27  ;

         ID  PARENT_ID          S
----------- ---------- ----------
          1                     6
          2          1          4
          3          1          2
          4          2          2
          5          2          1
          6          3          1
          7          3          1
          8          4          1

8 rows selected.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Агрегация сумм в иерархических запросах
    #39462772
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У кого есть в наличии 12.2 можете попробовать выполнить с закоментированным правилом вместо активного
Код: 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.
49.
50.
51.
52.
53.
with t(id, parent_id, description, amount) as
(
  select 1 id, null, 'top', 10  from dual
  union all select 2, 1, 'top-one', 100 from dual
  union all select 3, 2, 'one-one', 2000 from dual
  union all select 4, 2, 'one-two', 3000 from dual
  union all select 5, 1, 'top-two', 1000 from dual
  union all select 6, 2, 'one-three', 300 from dual
  union all select 7, 6, 'three-one', 1 from dual
)
, h as
(
  select id, parent_id, description, amount, level l, rownum rn
    from t
   start with id = 1
 connect by parent_id = prior id
)
select *
  from (select h.*,
               power(2 * 10, 1 - l) x,
               sum(power(2 * 10, 1 - l)) over(order by rn) s
          from h) h0
match_recognize
(
  order by rn
  measures
    first (id) as id,
    first (parent_id) as parent_id,
    first (l) as l,
    first (rn) as rn,
    first (amount) as amount,
    final count(*)-1 cnt_children,
    final sum(amount) h_sum
  one row per match
  after match skip to next row
  pattern (y+)
  define
    y as sum(x) < 2 * first(x)
    --ORA-03113, 12.1.0.2
    --y as max(s) - min(s) < first(x)
) mr;

        ID  PARENT_ID          L         RN     AMOUNT CNT_CHILDREN      H_SUM
---------- ---------- ---------- ---------- ---------- ------------ ----------
         1                     1          1         10            6       6411
         2          1          2          2        100            4       5401
         3          2          3          3       2000            0       2000
         4          2          3          4       3000            0       3000
         6          2          3          5        300            1        301
         7          6          4          6          1            0          1
         5          1          2          7       1000            0       1000

7 rows selected.



С all rows вместо one row все ок, но все строки для каждого матча здесь не нужны.
Код: 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.
with t(id, parent_id, description, amount) as
(
  select 1 id, null, 'top', 10  from dual
  union all select 2, 1, 'top-one', 100 from dual
  union all select 3, 2, 'one-one', 2000 from dual
  union all select 4, 2, 'one-two', 3000 from dual
  union all select 5, 1, 'top-two', 1000 from dual
  union all select 6, 2, 'one-three', 300 from dual
  union all select 7, 6, 'three-one', 1 from dual
)
, h as
(
  select id, parent_id, description, amount, level l, rownum rn
    from t
   start with id = 1
 connect by parent_id = prior id
)
select *
  from (select h.*,
               power(2 * 10, 1 - l) x,
               sum(power(2 * 10, 1 - l)) over(order by rn) s
          from h) h0
match_recognize
(
  order by rn
  measures
    final count(*)-1 cnt_children,
    final sum(amount) h_sum,
    count(*) cnt
  all rows per match
  after match skip to next row
  pattern (y+)
  define
    y as max(s) - min(s) < first(x)
) mr
where cnt = 1;

        RN CNT_CHILDREN      H_SUM        CNT         ID  PARENT_ID DESCRIPTI     AMOUNT          L          X          S
---------- ------------ ---------- ---------- ---------- ---------- --------- ---------- ---------- ---------- ----------
         1            6       6411          1          1            top               10          1          1          1
         2            4       5401          1          2          1 top-one          100          2        .05       1.05
         3            0       2000          1          3          2 one-one         2000          3      .0025     1.0525
         4            0       3000          1          4          2 one-two         3000          3      .0025      1.055
         5            1        301          1          6          2 one-three        300          3      .0025     1.0575
         6            0          1          1          7          6 three-one          1          4    .000125   1.057625
         7            0       1000          1          5          1 top-two         1000          2        .05   1.107625

7 rows selected.
...
Рейтинг: 0 / 0
13 сообщений из 63, страница 3 из 3
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Агрегация сумм в иерархических запросах
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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