powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / спецификация окна в listagg
23 сообщений из 23, страница 1 из 1
спецификация окна в listagg
    #39340938
bhr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
bhr
Гость
Всем здрасти.

with a as (select 1 id, 1 srt,'txt1' txt
from dual
union all
select 1 , 2 ,'txt2'
from dual
union all
select 1 , 3 ,'txt3'
from dual
union all
select 1 , 4 ,'txt4'
from dual
union all
select 1 , 5 ,'txt5'
from dual
union all
select 1 , 6 ,'txt6'
from dual)
select a.*,
listagg(a.txt,', ') within group(order by a.srt) over (partition by id ) lstagg,
sum(a.srt) over(partition by id order by a.srt ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) sm

from a

в функции sum спецификацию окна могу задать. а в листагг - никак.
Так задумано или я чегото не знаю?
и еще... как задать спецификацию окна чтоб в агрегации участвовали первые 10 строк партиции?
наверно, не у меня одного такая проблема - ограничить количество сцепляемых строк listagg первыми n строками.
Я, конечно, извратился и нашел решение. Но хотелось бы стандартными способами. без извратов.
Буду благодарен любому совету.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39340953
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bhr,

Тут ноги растут прежде всего из факта, что склейка строк не коммутативная операция в отличие от других.
То есть a || b <> b || a в отличие, например, от суммы или среднего.

Соответственно listagg позволяет указывать сортировку результата, но не сортировку окна.
С другой стороны stragg позволяет сортировать в окне, но сортировку в результирующей строке указать невозможно. Это вполне закономерно, поскольку в UDAG не предусмотрена возможность учитывать некоммутативность операции.

Возвращаясь к listagg, не совсем понятно почему не сделали возможность указывать order by (и distinct, но это другая проблема и более легко решаемая).
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39340963
ora601
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bhr,

"как задать спецификацию окна чтоб в агрегации участвовали первые 10 строк партиции? "

Как вариант - пронумеровать сначало row_number()
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39340975
bhr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
bhr
Гость
dbms_photoshopbhr,

Тут ноги растут прежде всего из факта, что склейка строк не коммутативная операция в отличие от других.
То есть a || b <> b || a в отличие, например, от суммы или среднего.

Соответственно listagg позволяет указывать сортировку результата, но не сортировку окна.
С другой стороны stragg позволяет сортировать в окне, но сортировку в результирующей строке указать невозможно. Это вполне закономерно, поскольку в UDAG не предусмотрена возможность учитывать некоммутативность операции.

Возвращаясь к listagg, не совсем понятно почему не сделали возможность указывать order by (и distinct, но это другая проблема и более легко решаемая).
то есть сделать это невозможно?
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39340983
bhr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
bhr
Гость
ora601bhr,

"как задать спецификацию окна чтоб в агрегации участвовали первые 10 строк партиции? "

Как вариант - пронумеровать сначало row_number()
и?
ограничить выборку первыми десятью строчками партиции?
мне нужны все строчки. и чтоб у двадцатой строки была агрегация первых 10 сточек.
я конечно использовал row_number() и использовал listagg group by/ а потом основную таблицу связывал с этой агрегацией.
Но хотелось бы через аналитические функции.
И еще.... фиг с ней с листагг. неужели нет простого способа задать окно "первые десять строчек"?
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39340991
ora601
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bhrora601bhr,

"как задать спецификацию окна чтоб в агрегации участвовали первые 10 строк партиции? "

Как вариант - пронумеровать сначало row_number()

ограничить выборку первыми десятью строчками партиции?

sum() over(order by rn range between 1 AND 10) .

Простого способа нет)
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39340994
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bhr,

Для твоей задачи просто создай и используй stragg, там можно указывать определения окна по строкам.

Если же стоит цель, например аналитическая склейка и результат в обратном порядке (столбец col в примере ниже), то тут никак listagg/stragg не помогут.
Решается встроенными функциями через склейку всего + regexp или через PL/SQL
Про решения через model и recursive subquery factoring речь не идет ибо баловство.

Код: plsql
1.
2.
3.
4.
5.
6.
select a.*,
       f(cast(collect(cast(a.txt as varchar2(100))) over (partition by id) as sys.odcivarchar2list), srt) col,
       cast(str_agg(a.txt || ' ') over (partition by id order by a.srt) as varchar2(4000)) stragg,
       listagg(a.txt, ', ') within group (order by a.srt desc) over (partition by id) lstagg
  from a
order by srt



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
        ID        SRT TXT  COL                                 STRAGG                              LSTAGG                             
---------- ---------- ---- ----------------------------------- ----------------------------------- -----------------------------------
         1          1 txt1 txt1                                txt1                                txt6, txt5, txt4, txt3, txt2, txt1 
         1          2 txt2 txt2 txt1                           txt1 txt2                           txt6, txt5, txt4, txt3, txt2, txt1 
         1          3 txt3 txt3 txt2 txt1                      txt1 txt2 txt3                      txt6, txt5, txt4, txt3, txt2, txt1 
         1          4 txt4 txt4 txt3 txt2 txt1                 txt1 txt2 txt3 txt4                 txt6, txt5, txt4, txt3, txt2, txt1 
         1          5 txt5 txt5 txt4 txt3 txt2 txt1            txt1 txt2 txt3 txt4 txt5            txt6, txt5, txt4, txt3, txt2, txt1 
         1          6 txt6 txt6 txt5 txt4 txt3 txt2 txt1       txt1 txt2 txt3 txt4 txt5 txt6       txt6, txt5, txt4, txt3, txt2, txt1 

6 rows selected.

f
Код: plsql
1.
2.
3.
4.
5.
6.
create or replace function f(c in sys.odcivarchar2list, n in number) return varchar2 as
result varchar2(4000);
begin
  for i in reverse 1..n loop result := result || c(i) || ' '; end loop;
  return result;
end;

...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341006
ora601
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ora601bhrпропущено...


ограничить выборку первыми десятью строчками партиции?

sum() over(order by rn range between 1 AND 10) .

Простого способа нет)

Точнее :
Код: plsql
1.
select t.*, sum(CASE WHEN rn>10 THEN 0 ELSE a.srt END) over (order by n rows between unbounded preceding and unbounded following) FROM t
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341008
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ora601,

ТС спрашивает про склейку строк, а ты ему про сумму вещаешь.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341027
ora601
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopora601,

ТС спрашивает про склейку строк, а ты ему про сумму вещаешь.
Я ему вещаю про первые 10 строк в партиции, если что)
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341032
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ora601 Я ему вещаю про первые 10 строк в партиции, если что)

И что? LISTAGG не имеет windowing и посему не хавает ROWS/RANGE PRECEDING/FOLLOWING.

SY.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341033
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ora601dbms_photoshopora601,

ТС спрашивает про склейку строк, а ты ему про сумму вещаешь.
Я ему вещаю про первые 10 строк в партиции, если что)
Ему вроде как надо склейку, но даже если речь про сумму, то нет смысла указывать то, в чем нет надобности
ora601Точнее :
Код: plaintext
1.
select t.*, sum(CASE WHEN rn>10 THEN 0 ELSE a.srt END) over (partition by id order by n rows between unbounded preceding and unbounded following) FROM t
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341035
ora601
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYora601 Я ему вещаю про первые 10 строк в партиции, если что)

И что? LISTAGG не имеет windowing и посему не хавает ROWS/RANGE PRECEDING/FOLLOWING.

SY.

Я говорю за work-around, а не за решение в лоб. Тем более там вопрос не только по listagg, но и по аналитике.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341040
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bhr,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
select t.*, regexp_replace(lstagg || ' ', '^([^ ]+ ){' || to_char(srt - 1) || '}(([^ ]+ ){1,3})(.*)', '\2') moving_3
  from (select a.*,
               listagg(a.txt, ' ') within group (order by a.srt) over (partition by id) lstagg,
               listagg(case when srt <= 3 then a.txt end, ' ') within group (order by a.srt) over (partition by id) first_3,
               str_agg(a.txt || ' ') over (partition by id order by a.srt rows between current row and 2 following) stragg
          from a
        order by srt) t



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
        ID        SRT TXT  LSTAGG                              FIRST_3         STRAGG          MOVING_3       
---------- ---------- ---- ----------------------------------- --------------- --------------- ---------------
         1          1 txt1 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt1 txt2 txt3  txt1 txt2 txt3 
         1          2 txt2 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt2 txt3 txt4  txt2 txt3 txt4 
         1          3 txt3 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt3 txt4 txt5  txt3 txt4 txt5 
         1          4 txt4 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt4 txt5 txt6  txt4 txt5 txt6 
         1          5 txt5 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt5 txt6       txt5 txt6      
         1          6 txt6 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt6            txt6           
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341060
bhr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
bhr
Гость
в теме действительно два вопроса. не хотел создавать две темы.
Спасибо за наводку по поводу ограничения первых 10 строк.
Listagg - пока не понял. пошел по указанной ссылке (asktom). понял, что создается собственная аналитическая ф-я.
Я никогда своих аналитических функций не создавал. Посоветуйте, что почитать (желательно ссылку).
Спасибо
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341077
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bhr,

Тебе так сложно взять непонятное слово и вбить в гугл?
Например, "ODCIAggregateInitialize oracle magazine" добавив oracle magazine чтоб было понятно "для самых маленьких" без лишних технических деталей.

Первой ссылкой ты увидишь Build Custom Aggregate Functions
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341087
bhr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
bhr
Гость
dbms_photoshopbhr,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
select t.*, regexp_replace(lstagg || ' ', '^([^ ]+ ){' || to_char(srt - 1) || '}(([^ ]+ ){1,3})(.*)', '\2') moving_3
  from (select a.*,
               listagg(a.txt, ' ') within group (order by a.srt) over (partition by id) lstagg,
               listagg(case when srt <= 3 then a.txt end, ' ') within group (order by a.srt) over (partition by id) first_3,
               str_agg(a.txt || ' ') over (partition by id order by a.srt rows between current row and 2 following) stragg
          from a
        order by srt) t



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
        ID        SRT TXT  LSTAGG                              FIRST_3         STRAGG          MOVING_3       
---------- ---------- ---- ----------------------------------- --------------- --------------- ---------------
         1          1 txt1 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt1 txt2 txt3  txt1 txt2 txt3 
         1          2 txt2 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt2 txt3 txt4  txt2 txt3 txt4 
         1          3 txt3 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt3 txt4 txt5  txt3 txt4 txt5 
         1          4 txt4 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt4 txt5 txt6  txt4 txt5 txt6 
         1          5 txt5 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt5 txt6       txt5 txt6      
         1          6 txt6 txt1 txt2 txt3 txt4 txt5 txt6       txt1 txt2 txt3  txt6            txt6           



спасибо.
listagg(case when srt <= 3 then a.txt end, ' ,') within group (order by a.srt) over (partition by id) first_3
именно то что нужно!!! этого и пытался добиться.

regexp_replace(lstagg || ' ', '^([^ ]+ ){' || to_char(srt - 1) || '}(([^ ]+ ){1,3})(.*)', '\2') moving_3
не то
задача возникла изза ошибки оракла при попытке применить listagg к партиции размером в 5000 строк.
нужно было ввести ограничение. причем сцепить и потом отрезать не получится, ибо оракл выдает ошибку в момент сцепки.
а case внутри listagg - очень красиво. Чето я ступил в свое время. Не додумкал.
спасибо еще раз. возьму на вооружение. Просто и изящно.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341100
bhr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
bhr
Гость
dbms_photoshopbhr,

Тебе так сложно взять непонятное слово и вбить в гугл?
Например, "ODCIAggregateInitialize oracle magazine" добавив oracle magazine чтоб было понятно "для самых маленьких" без лишних технических деталей.

Первой ссылкой ты увидишь Build Custom Aggregate Functions
а как я мог догадаться, что сии названия функций - предопределенные, а не придуманные сиюминутно автором статьи?
За наводку - спасибо. Готов согласиться, что я дурак, лишь бы получить нужные знания.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341118
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Рекурсивный CTE:

Код: 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.
54.
55.
56.
57.
58.
59.
60.
61.
62.
with e as (
           select  ename,
                   null ename_list,
                   row_number() over(order by ename) rn,
                   -2 window_start,
                   2 window_end
             from  emp
         ),
     r(
       ename,
       ename_list,
       rn,
       window_start,
       window_end
      ) as (
             select  *
               from  e
            union all
             select  r.ename,
                     case
                       when e.ename is null then r.ename_list
                       when r.ename_list is null then e.ename
                       else r.ename_list || ',' || e.ename
                     end,
                     r.rn,
                     r.window_start + 1,
                     r.window_end
               from  r,
                     e
               where e.rn(+) = r.rn + r.window_start
                 and r.window_start <= r.window_end
           )
select  ename,
        ename_list
  from  r
  where window_start = window_end + 1
  order by rn
/

ENAME      ENAME_LIST
---------- ---------------------------------
ADAMS      ADAMS,ALLEN,BLAKE
ALLEN      ADAMS,ALLEN,BLAKE,CLARK
BLAKE      ADAMS,ALLEN,BLAKE,CLARK,FORD
CLARK      ALLEN,BLAKE,CLARK,FORD,JAMES
FORD       BLAKE,CLARK,FORD,JAMES,JONES
JAMES      CLARK,FORD,JAMES,JONES,KING
JONES      FORD,JAMES,JONES,KING,MARTIN
KING       JAMES,JONES,KING,MARTIN,MILLER
MARTIN     JONES,KING,MARTIN,MILLER,SCOTT
MILLER     KING,MARTIN,MILLER,SCOTT,SMITH
SCOTT      MARTIN,MILLER,SCOTT,SMITH,TURNER

ENAME      ENAME_LIST
---------- ---------------------------------
SMITH      MILLER,SCOTT,SMITH,TURNER,WARD
TURNER     SCOTT,SMITH,TURNER,WARD
WARD       SMITH,TURNER,WARD

14 rows selected.

SQL> 



SY.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341129
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если LISTAGGируемые значения уникальны и ename не содержит спецсимволов regexp:

Код: 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.
with e as (
           select  ename,
                   listagg(ename,',') within group(order by ename) over() ename_list
             from  emp
         )
select  ename,
        regexp_substr(
                      ename_list,
                      '([^,]+,){0,2}' || ename || '(,[^,]+){0,2}'
                     ) ename_list
  from  e
/

ENAME      ENAME_LIST
---------- ----------------------------------
ADAMS      ADAMS,ALLEN,BLAKE
ALLEN      ADAMS,ALLEN,BLAKE,CLARK
BLAKE      ADAMS,ALLEN,BLAKE,CLARK,FORD
CLARK      ALLEN,BLAKE,CLARK,FORD,JAMES
FORD       BLAKE,CLARK,FORD,JAMES,JONES
JAMES      CLARK,FORD,JAMES,JONES,KING
JONES      FORD,JAMES,JONES,KING,MARTIN
KING       JAMES,JONES,KING,MARTIN,MILLER
MARTIN     JONES,KING,MARTIN,MILLER,SCOTT
MILLER     KING,MARTIN,MILLER,SCOTT,SMITH
SCOTT      MARTIN,MILLER,SCOTT,SMITH,TURNER

ENAME      ENAME_LIST
---------- ----------------------------------
SMITH      MILLER,SCOTT,SMITH,TURNER,WARD
TURNER     SCOTT,SMITH,TURNER,WARD
WARD       SMITH,TURNER,WARD

14 rows selected.

SQL> 



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

А вы читаете сообщения в топике, кроме своих?
Я уже вроде как сообщил что CTE - баловство и привел решения с regexp и PL/SQL.
С объяснением сопутствующих деталей.
...
Рейтинг: 0 / 0
спецификация окна в listagg
    #39341163
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopЯ уже вроде как сообщил что CTE - баловство

И что? Я же не привел STRAGG еще раз. В допoлнение я привел CTE. Кроме того довольно затратно сортировать в ODCIAggregateMerge.

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

Если имеется хотя бы 100к строк, то для этой задачи recursive subquery factoring не жилец в сравнении с другими альтернативами.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / спецификация окна в listagg
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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