#sql #oracle #plsql #plsql_developer
Добрый день. Т.к. от программирования далек, но в виду производственной необходимости в это дело ввязался, прошу помочь с написанием процедуры в oracle plsql developer (буду признателен за помощь в создании алгоритма так же). Суть такова - есть первый столбец (условно ID, в моем контексте не уникальный), и второй столбец, назову его "признаком". В базе это хранится в таком виде ID Признак 1 Красный 1 Темно-красный 2 Синий 2 Бирюзовый Необходимо написать процедуру такого рода - все признаки, соответствующие одинаковому ID, пишутся в одну ячейку. Т.е. так: ID Признак (применение процедуры) 1 Красный, (или ;) Темно-красный 2 Синий, Бирюзовый Буду крайне признателен за помощь! В виду необходимости скидываю сам кусок селекта: (case when (row_number() over(partition by (select dd.name from metrology.document dd where dd.id in (select **max(d.document_id)** from metrology.eqtype_document d where d.EQUIPMENT_TYPE_ID = e.id)) order by e.name)) = 1 then (select dd.name from metrology.document dd where dd.id in (select **max(d.document_id)** from metrology.eqtype_document d where d.EQUIPMENT_TYPE_ID = e.id)) end) as doc_name_to_form Символами ** отмечен участок кода, из за которого возникает весь сыр-бор. Max там включен чисто для работоспособности - данный участок селекта возвращает более одной строки и вызывает ошибку ora, поэтому я его max-ом искуссвенно урезал до одного возвращаемого результата. Но дело в том, что в 70% случаев данный участок должен возвращать более одного значения, для чего и необходима конкатенация, и я не знаю, как сюда инъектировать какой либо код.
Ответы
Ответ 1
Как вариант, если не заработают wm_conat или sys_xmlagg, сборка рекурсивным CTE: with Src(ID, Color, RN) as( select ID, Color, row_number() over(partition by ID order by NULL) RN from tab ), Tree(ID,color,RN) as( select ID, Color, RN from Src where RN=1 union all select T.ID,T.Color||','||S.Color,S.RN from Tree T, Src S where S.ID=T.ID and S.RN=T.RN+1 ) select * from Tree Или такой вариант (при наличии sys_connect_by_path): select ID, substr(max(sys_connect_by_path(Color,',')),2) from ( select ID, Color, row_number() over(partition by ID order by NULL) RN from tab ) start with RN=1 connect by ID=prior ID and RN=prior RN+1 group by Id Или сделать функцию, получающую строку по ID, что возможно удобнее для применения в выходных формах: create or replace function get_colors(ID_ number) return varchar2 is result varchar2(4000); begin result:=NULL; for C in(select accname from v1users where vidid=ID_) loop if length(result)+length(C.accname) > 3996 then return substr(result||',...',2); end if; result:=result||','||C.accname; end loop; return substr(result,2); end;Ответ 2
Получить нужный результат можно таким запросом: select id, to_char(wm_concat("Признак")) as "Признак" from table group by id Следует заметить, что wm_concat функция недокументированная и в проме ее использовать не всегда разумно. Если wm_concat не подходит, можно использовать XML: select id, CAST(RTRIM(Sys_xmlagg(XMLELEMENT(col, id||', ')).extract('/ROWSET/COL/text()').getclobval(), ', ') AS VARCHAR2(4000)) as "Признак" FROM table group by id col - это Ваша колонка Признак. Использовать русское наименование колонки у меня не получилось. В обоих вариантах могут быть проблемы с сортировкой значений.
Комментариев нет:
Отправить комментарий