powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос про wm_concat и сортировку
19 сообщений из 19, страница 1 из 1
Вопрос про wm_concat и сортировку
    #39320822
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подскажите, можно ли добиться от wm_concat предсказуемого поведения (Oracle 10g) или если нужен упорядоченный список, то эта функция в принципе не подходит?
Допустим я делаю так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
with rs as
(
  select ... as BASE, ... as CLIENT, ...
  ...
  --order by BASE, CLIENT
)
select BASE
, wm_concat(CLIENT) as CLIENTS
, count(*) as COUNT
from rs
group by BASE
order by BASE


Этот запрос (с закомментированной сортировкой в подзапросе) возвращает неупорядоченный список клиентов.
Если я включаю сортировку в подзапросе (раскомментирую), то как мне кажется, у Oracle нет причин переставлять значения при сортировке и список клиентов должен получится упорядоченным.
В целом он действительно упорядочен, однако не совсем. Первая половина списка упорядочена по возрастанию, вторая половина списка в основном упорядочена по убыванию, но не всегда. Примены:
0097,0104,0130,0631,1132,2577,2831,3354,5394, 3198,2770,1471,1057,0420
1094,4311,4831,5432,6339, 5186,4352,3148,1134,2681,2990

Этому есть какое-то объяснение?
Или недокументированную функцию тут использовать нельзя и следует использовать model или xmlagg?

________________________
Мы смотрим с оптимизмом...
...в оптический прицел.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39320835
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Используйте listagg(client,',') WITHIN GROUP (ORDER BY...)
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39320837
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Разве listagg не с 11 версии появился?
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39320844
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Разве listagg не с 11 версии появился?
До того были кастомные реализации - поищите stragg
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39320851
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Напиши свой агрегат с программной сортировкой внутри.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39320880
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну своя реализация это перебор, тогда уж лучше модель использовать.
Просто я надеялся, что тут можно wm_concat приспособить, мне простота ее использования нравится.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39320967
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Ну своя реализация это перебор
Два часа работы + новый полезный опыт.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325032
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
63.
CREATE OR REPLACE TYPE string_agg_type as object
(
       total varchar2(4000),
       static function
            ODCIAggregateInitialize(sctx IN OUT string_agg_type )
            return number,
       member function
           ODCIAggregateIterate(self IN OUT string_agg_type ,
                                value IN varchar2 )
           return number,
       member function
           ODCIAggregateTerminate(self IN string_agg_type,
                                  returnValue OUT  varchar2,
                                  flags IN number)
           return number,
       member function
           ODCIAggregateMerge(self IN OUT string_agg_type,
                              ctx2 IN string_agg_type)
           return number
);
/

CREATE OR REPLACE TYPE BODY string_agg_type
is
    static function ODCIAggregateInitialize(sctx IN OUT string_agg_type)
    return number
    is
    begin
        sctx := string_agg_type( null );
        return ODCIConst.Success;
   end;
   member function ODCIAggregateIterate(self IN OUT string_agg_type,
                                        value IN varchar2)
   return number
   is
   begin
       self.total := self.total || ',' || value;
       return ODCIConst.Success;
   end;
   member function ODCIAggregateTerminate(self IN string_agg_type,
                                          returnValue OUT varchar2,
                                          flags IN number)
   return number
   is
   begin
       returnValue := ltrim(self.total,',');
       return ODCIConst.Success;
   end;
   member function ODCIAggregateMerge(self IN OUT string_agg_type,
                                      ctx2 IN string_agg_type)
   return number
   is
   begin
       self.total := self.total || ctx2.total;
       return ODCIConst.Success;
   end;
end;
/

CREATE OR REPLACE FUNCTION GROUP_CONCAT(input varchar2 )
RETURN varchar2
PARALLEL_ENABLE AGGREGATE USING string_agg_type;
/


Функция GROUP_CONCAT работает (идентично WM_CONCAT), т.е. строки соединяет, но не сортирует.
Не могу понять, как реализовать сортировку.
По идее, для этого должен быть интерфейс ODCIAggregateCompare (в котором я задаю логику сравнения элементов), но этого интерфейса в ODCIAggregate нет.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325230
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.По идее, для этого должен быть интерфейс ODCIAggregateCompareИ какие, по твоему, параметры должны быть у этого интерфейса, когда вызваться и что делать в реализации?
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325250
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обычно в подобных интерфейсах передается два сравниваемых значения (объекта), а реализация интерфейса должна вернуть результат их сравнения (первый больше второго, второй больше первого, они равны).
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325284
Alibek B.,

Как вариант, убрать метод ODCIAggregateMerge, тогда он не будет знать, как складывать результат иначе, чем в порядке прохода (который закрепить с помощью order by).

Другой вариант, результат складывать не в total varchar2, а в коллекцию, на выходе внутри ODCIAggregateTerminate уже сортировать и складывать в varchar2.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325352
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Обычно в подобных интерфейсах передается два сравниваемых значения (объекта), а реализация интерфейса должна вернуть результат их сравнения (первый больше второго, второй больше первого, они равны).И дальше что агрегатор должен делать с этим "больше"?
Ты путаешь с методами объектных типов order/map, которые вызываются явной сортировкой order by ASC/DESC NULLS FIRST/LAST. При этом попарное сравнение order применимо только в неэффективных алгоритмах сортировки с большим количеством сравнений.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325360
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-Ты путаешь с методами объектных типов order/map, которые вызываются явной сортировкой order by ASC/DESC NULLS FIRST/LAST. При этом попарное сравнение order применимо только в неэффективных алгоритмах сортировки с большим количеством сравнений.
Да, теперь понял.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325362
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Не могу понять, как реализовать сортировку.


А зачем придумывать велосипед. Убери MERGE и:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SQL> select stragg(ename) from emp;

STRAGG(ENAME)
------------------------------------------------------------------------------------------
SMITH,ALLEN,WARD,JONES,MARTIN,BLAKE,CLARK,SCOTT,KING,TURNER,ADAMS,JAMES,FORD,MILLER

Elapsed: 00:00:00.90
SQL> with t as (select ename from emp order by ename)
  2  select stragg(ename) from t;

STRAGG(ENAME)
------------------------------------------------------------------------------------------
ADAMS,ALLEN,BLAKE,CLARK,FORD,JAMES,JONES,KING,MARTIN,MILLER,SCOTT,SMITH,TURNER,WARD

Elapsed: 00:00:00.03
SQL>



SY.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325810
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сорри за ленивый код.
Идея, как мне кажется, должна быть понятна
Код: 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.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
CREATE OR REPLACE TYPE string_agg_vch2_tab as table of varchar2(2000);

CREATE OR REPLACE TYPE string_agg_type as object
(
       coll string_agg_vch2_tab,
       static function
            ODCIAggregateInitialize(sctx IN OUT string_agg_type )
            return number,
       member function
           ODCIAggregateIterate(self IN OUT string_agg_type ,
                                value IN varchar2 )
           return number,
       member function
           ODCIAggregateTerminate(self IN string_agg_type,
                                  returnValue OUT  clob, --varchar2,
                                  flags IN number)
           return number,
       member function
           ODCIAggregateMerge(self IN OUT string_agg_type,
                              ctx2 IN string_agg_type)
           return number
)
/

CREATE OR REPLACE TYPE BODY string_agg_type
is
    static function ODCIAggregateInitialize(sctx IN OUT string_agg_type)
    return number
    is
    begin
        sctx := string_agg_type( string_agg_vch2_tab() );
        return ODCIConst.Success;
   end;
   member function ODCIAggregateIterate(self IN OUT string_agg_type,
                                        value IN varchar2)
   return number
   is
   begin
       self.coll.extend;
       self.coll(self.coll.count) := value;
       return ODCIConst.Success;
   end;
   member function ODCIAggregateTerminate(self IN string_agg_type,
                                          returnValue OUT clob, --varchar2,
                                          flags IN number)
   return number
   is
     type ltt is table of int index by varchar2(2000);
     lt ltt;
     idx varchar2(2000);
   begin
       -- зело ленив я сортировку писать.
       for i in 1..self.coll.count() loop
         if lt.exists(self.coll(i)) then
           lt(self.coll(i)) := lt(self.coll(i)) + 1;
         else
           lt(self.coll(i)) := 1;
         end if;
       end loop;

       idx := lt.first;
       while idx is not null loop
         for i in 1..lt(idx) loop
           returnValue := case when returnValue is not null then returnValue||','||idx else idx end;
         end loop;
         idx := lt.next(idx);
       end loop;

       return ODCIConst.Success;
   end;
   member function ODCIAggregateMerge(self IN OUT string_agg_type,
                                      ctx2 IN string_agg_type)
   return number
   is
   begin
       self.coll := self.coll multiset union all ctx2.coll;
       return ODCIConst.Success;
   end;
end;
/

CREATE OR REPLACE FUNCTION GROUP_CONCAT(input varchar2 )
RETURN varchar2
PARALLEL_ENABLE AGGREGATE USING string_agg_type;
/
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325811
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325827
дфяян ыщке
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousСорри за ленивый код.не проще ли тогда сортировать в iterate.
andrey_anonymouscollect прикручиваютxmlagg(','||)+.extract+ltrim столько-же-буквенно, но без дополнительных функций.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39325996
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
дфяян ыщкене проще ли тогда сортировать в iterate.
Если я правильно понял, то ленивость заключается в том, что в iterate вместо индексирования просто проставляются последовательные номера.
А в terminate осуществляется не сортировка, а выборка данных по индексу.
...
Рейтинг: 0 / 0
Вопрос про wm_concat и сортировку
    #39327526
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.дфяян ыщкене проще ли тогда сортировать в iterate.
Если я правильно понял, то ленивость заключается в том, что в iterate вместо индексирования просто проставляются последовательные номера.
А в terminate осуществляется не сортировка, а выборка данных по индексу.
Нет.
Ленивость - в том, что я поленился кодить сортировку и вместо сортировки использовал ассоциативный массив, что удвоило необходимую память.
Кроме того, этот подход не дает возможности сделать linguistic sort.

И еще одно Нет: в iterate не "проставляются последовательные номера", а подсчитываются дубликаты - нигде не сказано, что сортируемое множество уникально.
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос про wm_concat и сортировку
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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