PL / SQL эквивалент объединения переменных, ориентированных на набор, T-SQL

#sql #oracle #plsql #string-aggregation

#sql #Oracle #plsql #агрегация строк

Вопрос:

В Microsoft SQL Server (T-SQL) существует краткий, элегантный и производительный способ заполнения переменной VARCHAR с помощью объединения значений из нескольких строк в таблице, т.Е.:

 DECLARE @vals NVARCHAR(MAX)
SELECT @vals = ISNULL(@vals   ',', '')
  <some_varchar_column>
FROM <some_table>
  

Заполняет @vals разделенной запятыми строкой всех значений в some_column из всех строк some_table (например, «значение1, значение2, значение3, …»).

Как мне сделать что-то подобное в Oracle PL / SQL таким же элегантным способом (без необходимости написания цикла / курсора)?

Ответ №1:

Это?

 SQL> select listagg(dname, ',') within group (order by dname) result
  2  from dept;

RESULT
-------------------------------------------------------------------------
ACCOUNTING,OPERATIONS,RESEARCH,SALES

SQL>
  

Ответ №2:

Иногда имеет смысл реализовать собственную функцию. это действительно просто (db<>fiddle):

 select * from vals
/
        ID VAL                                          
---------- ---------------------------------------------
         1 value1                                       
         1 value2                                       
         2 value3                                       
         2 value4                                       
         2 value5                                       
         3 value6                                       

create or replace type listofvals is table of varchar2 (64)
/
with function mylistagg (vals listofvals, delimiter char := ',') return varchar2 is
    ret varchar2 (32767);
begin 
    for i in 1..vals.count loop 
        ret := ret||vals(i)||delimiter; end loop;
    return rtrim (ret, delimiter);
end; 
select id, mylistagg (cast (collect (val order by val) as listofvals), ' -> ') res
from vals
group by id
/
  

Результат:

         ID RES                             
---------- --------------------------------
         1 value1->value2                  
         2 value3->value4->value5          
         3 value6