Seria possível construir SQL para concatenar valores de colunas de várias linhas?
A seguir, um exemplo:
Quadro A
PID UMA B C
Quadro B
PQ SEQ Desc A 1 Have A 2 um bom Um dia 3. B 1 Bom trabalho. C 1 sim C 2 podemos C 3 do C 4 esse trabalho!
A saída do SQL deve ser -
PID Desc Tenha um bom dia. B Bom trabalho. C Sim, podemos fazer este trabalho!
Então, basicamente, a coluna Desc para a tabela de saída é uma concatenação dos valores SEQ da Tabela B?
Alguma ajuda com o SQL?
sql
oracle
string-aggregation
jagamota
fonte
fonte
Respostas:
Existem algumas maneiras, dependendo da versão que você possui - consulte a documentação do Oracle sobre técnicas de agregação de strings . Um muito comum é usar
LISTAGG
:Em seguida, junte-se a
A
para escolher opids
que deseja.Nota: Fora da caixa,
LISTAGG
funciona apenas corretamente comVARCHAR2
colunas.fonte
Há também uma
XMLAGG
função que funciona em versões anteriores à 11.2. Como nãoWM_CONCAT
é documentado e não é suportado pela Oracle , é recomendável não usá-lo no sistema de produção.Com
XMLAGG
você pode fazer o seguinte:O que isso faz é
ename
coluna (concatenados com vírgula) daemployee_names
tabela em um elemento xml (com a tag E)fonte
Com a cláusula de modelo SQL:
Eu escrevi sobre isso aqui . E se você seguir o link para o thread OTN, encontrará mais alguns, incluindo uma comparação de desempenho.
fonte
A função analítica LISTAGG foi introduzida no Oracle 11g Release 2 , facilitando a agregação de strings. Se você estiver usando o 11g Release 2, deverá usar esta função para agregação de strings. Consulte o URL abaixo para obter mais informações sobre concatenação de strings.
http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php
Concatenação de String
fonte
Como a maioria das respostas sugere,
LISTAGG
é a opção óbvia. No entanto, um aspecto irritanteLISTAGG
é que, se o comprimento total da string concatenada exceder 4000 caracteres (limite paraVARCHAR2
SQL), será gerado o erro abaixo, que é difícil de gerenciar nas versões Oracle até 12.1Um novo recurso adicionado ao 12cR2 é a
ON OVERFLOW
cláusula deLISTAGG
. A consulta incluindo esta cláusula seria semelhante a:O acima irá restringir a saída a 4000 caracteres, mas não emitirá o
ORA-01489
erro.Estas são algumas das opções adicionais da
ON OVERFLOW
cláusula:ON OVERFLOW TRUNCATE 'Contd..'
: Isso será exibido'Contd..'
no final da string (o padrão é...
)ON OVERFLOW TRUNCATE ''
: Isso exibirá os 4000 caracteres sem nenhuma sequência final.ON OVERFLOW TRUNCATE WITH COUNT
: Isso exibirá o número total de caracteres no final após os caracteres finais. Por exemplo: - '...(5512)
'ON OVERFLOW ERROR
: Se você espera que aLISTAGG
falha com oORA-01489
erro (que é o padrão de qualquer maneira).fonte
Para aqueles que precisam resolver esse problema usando o Oracle 9i (ou anterior), provavelmente será necessário usar o SYS_CONNECT_BY_PATH, pois o LISTAGG não está disponível.
Para responder ao OP, a seguinte consulta exibirá o PID da Tabela A e concatenará todas as colunas DESC da Tabela B:
Também pode haver casos em que chaves e valores estão todos contidos em uma tabela. A consulta a seguir pode ser usada onde não há Tabela A e existe apenas a Tabela B:
Todos os valores podem ser reordenados conforme desejado. Descrições concatenadas individuais podem ser reordenadas na cláusula PARTITION BY e a lista de PIDs pode ser reordenada na cláusula ORDER BY final.
Como alternativa: pode haver momentos em que você deseja concatenar todos os valores de uma tabela inteira em uma linha.
A idéia principal aqui é usar um valor artificial para o grupo de descrições a serem concatenadas.
Na consulta a seguir, a cadeia constante '1' é usada, mas qualquer valor funcionará:
Descrições concatenadas individuais podem ser reordenadas na cláusula PARTITION BY.
Várias outras respostas nesta página também mencionaram essa referência extremamente útil: https://oracle-base.com/articles/misc/string-aggregation-techniques
fonte
O LISTAGG oferece o melhor desempenho se a classificação for obrigatória (00: 00: 05.85)
SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;
COLLECT oferece o melhor desempenho se a classificação não for necessária (00: 00: 02.90):
SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
COLECIONAR com a encomenda é um pouco mais lento (00: 00: 07.08):
SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
Todas as outras técnicas foram mais lentas.
fonte
Antes de executar uma consulta de seleção, execute o seguinte:
SET SERVEROUT ON SIZE 6000
fonte
Tente este código:
fonte
Na seleção onde deseja sua concatenação, chame uma função SQL.
Por exemplo:
Em seguida, para a função SQL:
A sintaxe do cabeçalho da função pode estar errada, mas o princípio funciona.
fonte