Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос про wm_concat и сортировку / 19 сообщений из 19, страница 1 из 1
05.10.2016, 11:07
    #39320822
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Подскажите, можно ли добиться от 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
05.10.2016, 11:19
    #39320835
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Используйте listagg(client,',') WITHIN GROUP (ORDER BY...)
...
Рейтинг: 0 / 0
05.10.2016, 11:20
    #39320837
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Разве listagg не с 11 версии появился?
...
Рейтинг: 0 / 0
05.10.2016, 11:28
    #39320844
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Alibek B.Разве listagg не с 11 версии появился?
До того были кастомные реализации - поищите stragg
...
Рейтинг: 0 / 0
05.10.2016, 11:31
    #39320851
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Alibek B.,

Напиши свой агрегат с программной сортировкой внутри.
...
Рейтинг: 0 / 0
05.10.2016, 11:53
    #39320880
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Ну своя реализация это перебор, тогда уж лучше модель использовать.
Просто я надеялся, что тут можно wm_concat приспособить, мне простота ее использования нравится.
...
Рейтинг: 0 / 0
05.10.2016, 13:05
    #39320967
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Alibek B.Ну своя реализация это перебор
Два часа работы + новый полезный опыт.
...
Рейтинг: 0 / 0
12.10.2016, 09:54
    #39325032
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Код: 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
12.10.2016, 12:34
    #39325230
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Alibek B.По идее, для этого должен быть интерфейс ODCIAggregateCompareИ какие, по твоему, параметры должны быть у этого интерфейса, когда вызваться и что делать в реализации?
...
Рейтинг: 0 / 0
12.10.2016, 12:57
    #39325250
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Обычно в подобных интерфейсах передается два сравниваемых значения (объекта), а реализация интерфейса должна вернуть результат их сравнения (первый больше второго, второй больше первого, они равны).
...
Рейтинг: 0 / 0
12.10.2016, 13:22
    #39325284
Вопрос про wm_concat и сортировку
Alibek B.,

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

Другой вариант, результат складывать не в total varchar2, а в коллекцию, на выходе внутри ODCIAggregateTerminate уже сортировать и складывать в varchar2.
...
Рейтинг: 0 / 0
12.10.2016, 14:35
    #39325352
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Alibek B.Обычно в подобных интерфейсах передается два сравниваемых значения (объекта), а реализация интерфейса должна вернуть результат их сравнения (первый больше второго, второй больше первого, они равны).И дальше что агрегатор должен делать с этим "больше"?
Ты путаешь с методами объектных типов order/map, которые вызываются явной сортировкой order by ASC/DESC NULLS FIRST/LAST. При этом попарное сравнение order применимо только в неэффективных алгоритмах сортировки с большим количеством сравнений.
...
Рейтинг: 0 / 0
12.10.2016, 14:42
    #39325360
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
-2-Ты путаешь с методами объектных типов order/map, которые вызываются явной сортировкой order by ASC/DESC NULLS FIRST/LAST. При этом попарное сравнение order применимо только в неэффективных алгоритмах сортировки с большим количеством сравнений.
Да, теперь понял.
...
Рейтинг: 0 / 0
12.10.2016, 14:42
    #39325362
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
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
13.10.2016, 03:43
    #39325810
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Сорри за ленивый код.
Идея, как мне кажется, должна быть понятна
Код: 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
13.10.2016, 03:46
    #39325811
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
...
Рейтинг: 0 / 0
13.10.2016, 06:41
    #39325827
дфяян ыщке
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
andrey_anonymousСорри за ленивый код.не проще ли тогда сортировать в iterate.
andrey_anonymouscollect прикручиваютxmlagg(','||)+.extract+ltrim столько-же-буквенно, но без дополнительных функций.
...
Рейтинг: 0 / 0
13.10.2016, 10:43
    #39325996
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
дфяян ыщкене проще ли тогда сортировать в iterate.
Если я правильно понял, то ленивость заключается в том, что в iterate вместо индексирования просто проставляются последовательные номера.
А в terminate осуществляется не сортировка, а выборка данных по индексу.
...
Рейтинг: 0 / 0
15.10.2016, 13:04
    #39327526
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос про wm_concat и сортировку
Alibek B.дфяян ыщкене проще ли тогда сортировать в iterate.
Если я правильно понял, то ленивость заключается в том, что в iterate вместо индексирования просто проставляются последовательные номера.
А в terminate осуществляется не сортировка, а выборка данных по индексу.
Нет.
Ленивость - в том, что я поленился кодить сортировку и вместо сортировки использовал ассоциативный массив, что удвоило необходимую память.
Кроме того, этот подход не дает возможности сделать linguistic sort.

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


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