2016-05-24 2 views
2

Я пытаюсь заставить функцию COLLECT работать для меня. Я использую 10g и поэтому обнаружил, что LISTAGG и WM_CONCAT не будут работать (неправильные ошибки идентификатора). Данные, которые у меня есть, например, следующие.Как использовать COLLECT с VARCHAR2 Oracle 10g

Order Lot 
123 A23088 
123 A23089 
089 AABBCC 
305 120848 
305 CCDDYY 

Что мне нужно Возвращаются следующим

Order Lot 
123  A23088, A23089 
089  AABBCC 
305  120848, CCDDYY 

Используя следующее, я получаю ошибку: TO_STRING является неверным идентификатором

TO_STRING (CAST(COLLECT(DISTINCT LOT) AS varchar2(100))) AS LOT 

Используя следующее, я получаю ошибку : ожидаемые CHAR "непоследовательные типы данных: ожидаемые% s получены% s"

TO_CHAR (CAST(COLLECT(DISTINCT LOT) AS varchar2(100))) AS LOT 

Используя следующее, я получаю ошибку: ожидаемое число «несогласованные типы данных: ожидалось% s% s получил»

COLLECT(DISTINCT WHSE_LOT) 

Есть ли способ, чтобы получить эту функцию, чтобы работать для меня?

ответ

1

collect function создает вложенную таблицу, в вашем случае таблицу строк, которую затем следует нанести на определенный тип, то есть тип, определенный как таблица varchar2. Вы не можете использовать одну строчку.

Есть некоторые известные списки методов агрегации струн, like this one. Существует один that uses collect, но вам все еще нужен тип таблицы и функция для преобразования сгенерированной таблицы в строку с разделителями.

Копирование этот пример дословно:

CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000); 
/

CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab IN t_varchar2_tab, 
              p_delimiter  IN VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS 
    l_string  VARCHAR2(32767); 
BEGIN 
    FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP 
    IF i != p_varchar2_tab.FIRST THEN 
     l_string := l_string || p_delimiter; 
    END IF; 
    l_string := l_string || p_varchar2_tab(i); 
    END LOOP; 
    RETURN l_string; 
END tab_to_string; 
/

С этого типа и функции, которые вы затем сделать:

SELECT tab_to_string(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab)) AS lot FROM ... 

Интересно, что the 10g version of collect не поддерживает DISTINCT; он не жалуется (!?), но оставляет дубликаты.

Вы можете передать коллекцию через the set function для удаления дубликатов:

SELECT tab_to_string(SET(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab))) AS lot FROM ... 

Быстрый демонстрационный пробег в 10.2.0.5:

create table table1(order_no number, lot varchar2(10)); 

insert into table1 values (590288, '2016538'); 
insert into table1 values (590288, '2016535'); 
insert into table1 values (590288, '6016535'); 
insert into table1 values (590288, '2016535'); 
insert into table1 values (590288, '2016538'); 

SELECT order_no, tab_to_string(SET(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab))) AS LOT 
FROM table1 WHERE order_no = 590288 GROUP BY order_no; 

    ORDER_NO LOT            
---------- -------------------------------------------------- 
    590288 2016538,2016535,6016535       
+0

Спасибо за помощь @AlexPoole. Я нашел это решение для работы с одним исключением - возвращаются не только отдельные значения. Например, 'SELECT order_no, tab_to_string (CAST (COLLECT (DISTINCT lot) AS t_varchar2_tab)) AS LOT FROM table1 WHERE order_no = 590288 GROUP BY order_no;' Возвращает Order_No Lot 590288 2016535,2016535,6016535,2016538,2016538 Любые предложения? – ESC

+0

@ESC - обновлено, чтобы передать коллекцию через 'SET()' для удаления сульфитов, поскольку 10g не распознает 'COLLECT (DISTINCT ...)'. –