Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como usar a função LISTAGG do Oracle


Função LISTAGG do Oracle é uma função analítica que nos permite concatenar as strings para meter_column para cada GROUP com base na order_by_clause. Isso está presente no Oracle a partir do 11gR2

A sintaxe para a função LISTAGG no Oracle é
LISTAGG (measure_column [, 'delimiter'])
WITHIN GROUP (order_by_clause) [OVER (query_partition_clause)]

Explicação dos termos
measure_column A coluna ou expressão cujos valores você deseja concatenar no conjunto de resultados. Valores nulos na medida_coluna são ignorados.
Delimitador Opcional. É o delimitador a ser usado ao separar a measure_column valores ao gerar os resultados.
order_by_clause Determina a ordem em que os valores concatenados são retornados

Vamos ver alguns casos e exemplos na função LISTAGG

1) Como uma função agregada de conjunto único, LISTAGG opera em todas as linhas e retorna uma única linha de saída.

SELECT LISTAGG(first_name, '; ')
WITHIN GROUP (ORDER BY hire_date, last_name) "Employee_list",
MIN(hire_date) "Earliest"
FROM emp
WHERE dept_no = 30;

Employee_list                                                Earliest
------------------------------------------------------------ ---------
TOM; BOB; BILL                                            17-JUN-18


2) Como um agregado de conjunto de grupos, a função opera e retorna uma linha de saída para cada grupo definido pela cláusula GROUP BY.
COLUMN employees FORMAT A50
SELECT deptno, LISTAGG(ename, ';') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;
DEPTNO EMPLOYEES
---------- --------------------------------------------------
10 JOSHUA,KING,MILLER
20 AJAY,FANES,SCOTT,SMITH
30 TOM; BOB; BILL

More Example

select table_name,
listagg(index_name, ',') within group (order by index_name) all_inds
from user_indexes
group by table_name;


3) Como uma função analítica, LISTAGG particiona o conjunto de resultados da consulta em grupos com base em uma ou mais expressões na query_partition_clause.

SQL> SELECT deptno
, ename
, hiredate
, LISTAGG(ename, ',')
WITHIN GROUP (ORDER BY hiredate)
OVER (PARTITION BY deptno) AS employees
FROM emp  order by deptno;

DEPTNO ENAME HIREDATE EMPLOYEES
---------- ---------- ----------- -------------------------------------
10 JOSHUA 09/06/2018 JOSHUA,KING,MILLER
10 KING 17/11/2018 JOSHUA,KING,MILLER
10 MILLER 23/01/2018 JOSHUA,KING,MILLER
20 AJAY 17/12/2018 AJAY,FANES,SCOTT,SMITH
20 FANES 02/04/2018 AJAY,FANES,SCOTT,SMITH
20 SCOTT 19/04/2018 AJAY,FANES,SCOTT,SMITH
20 SMITH 23/05/2018 AJAY,FANES,SCOTT,SMITH
30 TOM 20/02/2018 TOM; BOB; BILL
30 BOB 22/02/2018 TOM; BOB; BILL
30 BILL 01/05/2018 TOM; BOB; BILL

Adição na função LISTAGG do banco de dados Oracle 12cR2


O número máximo de retornos de caracteres é de 4000 bytes e se exceder, dá o erro

ORA-01489:o resultado da concatenação de strings é muito longo

Com o Oracle 12cR2, a Oracle forneceu uma cláusula sobre overflow truncate para lidar com erros de estouro normalmente

listagg (
measure, ','
[ on overflow (truncate|error) ]
[ text ] [ (with|without) count ]
) within group (order by cols)


Agora você pode dizer explicitamente se deseja erro ou semântica de truncamento. Os códigos pré 12cR2 funcionam bem, pois esse é o comportamento padrão

Agora suponha que você não queira retornar um erro quando ele cruzar 4k bytes, então no overflow truncate é a solução.

select table_name,
listagg(index_name, ',' on overflow truncate) within group (order by index_name) inds
from user_indexes
group by table_name;


Caso ocorra truncamento, o Oracle truncará de volta para o próximo valor completo. Nesse ponto, você poderá controlar como informará ao usuário que a lista foi truncada. Por padrão, anexamos três pontos ‘…’ à string como indicador de que ocorreu truncamento. Você pode alterar o '….' se quiser, pode substituir isso

Se você quiser substituir “…” por “mais”, “extra” ou um hiperlink “clique para mais”, basta fornecer sua nova string!

select table_name,
listagg(index_name, ',' on overflow truncate
'|||'
) within group (order by index_name) inds
from user_indexes
group by table_name;


Por padrão, truncate mostra a contagem de valores ausentes Se não quiser mostrar a contagem, use sem contagem

select table_name,
listagg(index_name, ',' on overflow truncate '....' without count) within group (order by index_name) inds
from user_indexes
group by table_name;


Solução pré 11GR2 (10g, 9i, 11gR1)

Se você não estiver executando o 11g Release 2 ou superior, mas estiver executando uma versão do banco de dados em que a função WM_CONCAT está presente, então é uma solução de esforço zero, pois executa a agregação para você. Na verdade, é um exemplo de uma função agregada definida pelo usuário descrita abaixo, mas a Oracle fez todo o trabalho para você.
COLUMN employees FORMAT A50
SELECT deptno, wm_concat(ename) AS employees
FROM emp
GROUP BY deptno;
EPTNO EMPLOYEES
---------- --------------------------------------------------
10 JOSHUA,KING,MILLER
20 AJAY,FANES,SCOTT,SMITH
30 TOM; BOB; BILL


Isso também pode ser feito por meio de uma função definida pelo usuário. Eu recomendaria verificar o link abaixo do asktom. Isso é leitura obrigatória

Opção alternativa Listagg

Espero que você goste do conteúdo desta postagem sobre a Função LISTAGG do Oracle
Artigos relacionados
Coluna de incremento automático - Sequência como valor padrão no Oracle e mysql
Juntos Oracle
Operadores de conjunto SQL
Como usar o URL do google translate no Oracle plsql
Funções de linha única em sql
função de data no oráculo