Antes do Oracle 11.2, eu estava usando uma função agregada personalizada para concatenar uma coluna em uma linha. 11.2 Adicionada a LISTAGG
função, então estou tentando usá-la. Meu problema é que preciso eliminar duplicatas nos resultados e não parece capaz de fazer isso.
Aqui está um exemplo.
CREATE TABLE ListAggTest AS (
SELECT rownum Num1, DECODE(rownum,1,'2',to_char(rownum)) Num2 FROM dual
CONNECT BY rownum<=6
);
SELECT * FROM ListAggTest;
NUM1 NUM2
---------- ---------------------
1 2
2 2 << Duplicate 2
3 3
4 4
5 5
6 6
O que eu quero ver é o seguinte:
NUM1 NUM2S
---------- --------------------
1 2-3-4-5-6
2 2-3-4-5-6
3 2-3-4-5-6
4 2-3-4-5-6
5 2-3-4-5-6
6 2-3-4-5-6
Aqui está uma listagg
versão que está próxima, mas não elimina duplicatas.
SELECT Num1, listagg(Num2,'-') WITHIN GROUP (ORDER BY NULL) OVER () Num2s
FROM ListAggTest;
Eu tenho uma solução, mas é pior do que continuar usando a função agregada personalizada.
oracle
oracle-11g-r2
aggregate
Leigh Riffel
fonte
fonte
order by null
estarorder by Num2
ou estou ficando confuso?LISTAGG
continua a ficar aquém do Tom Kyte deSTRAGG
, com o qual é tão fácil comoSTRAGG(DISTINCT ...)
Respostas:
Você pode usar expressões regulares e
regexp_replace
remover as duplicatas após a concatenação comlistagg
:Isso poderia ser mais organizado se o sabor de regex da Oracle suportasse grupos de aparência ou sem captura, mas não .
No entanto, esta solução evita verificar a fonte mais de uma vez.
DBFiddle aqui
fonte
ORDER BY Num2
alcança, não é (veja aqui ). Ou você está apenas tentando ressaltar que precisa do ORDER BY para que ele funcione?Tanto quanto posso ver, com a especificação de idioma atualmente disponível, este é o mais curto para alcançar o que você deseja, se for necessário
listagg
.Qual foi a sua solução pior do que a solução agregada personalizada ?
fonte
regexp
solução.Crie uma função agregada personalizada para fazer isso.
fonte
Embora este seja um post antigo com uma resposta aceita, acho que a função analítica LAG () funciona bem nesse caso e é digna de nota:
Aqui está o código proposto:
Os resultados abaixo parecem ser o que o OP deseja:
fonte
Aqui estava minha solução para o problema que, na minha opinião, não é tão bom quanto usar nossa função agregada personalizada que já existe.
fonte
Use WMSYS.WM_Concat em vez disso.
Nota: Esta função não é documentada e não é suportada. Consulte https://forums.oracle.com/forums/message.jspa?messageID=4372641#4372641 .
fonte
wm_concat
(mesmo se você argumentarwm_concat
que o problema não está causando o problema), eles teriam motivos para se recusar a ajudar porque não é documentado e não é suportado - não é o caso se você usar um agregado personalizado ou qualquer outro recurso suportado.Você também pode usar uma instrução collect e, em seguida, escrever uma função pl / sql personalizada que converta a coleção em uma string.
Você pode usar
distinct
eorder by
em umacollect
cláusula, mas se combinadodistinct
, não funcionará a partir de 11.2.0.2 :(A solução alternativa pode ser uma subseleção:
fonte
Criei esta solução antes de encontrar o ListAgg, mas ainda existem ocasiões, como esse problema de valor duplicado, e essa ferramenta é útil. A versão abaixo possui 4 argumentos para fornecer controle sobre os resultados.
Explicação O CLOBlist usa o contrator CLOBlistParam como um parâmetro. CLOBlistParam possui 4 argumentos
Exemplo de uso
O link para Gist está abaixo.
https://gist.github.com/peter-genesys/d203bfb3d88d5a5664a86ea6ee34eeca] 1
fonte
Eu sei que é algum tempo após a postagem original, mas este foi o primeiro local que encontrei após pesquisar no Google por uma resposta para o mesmo problema e pensei que alguém que chegou aqui pode ficar feliz em encontrar uma resposta sucinta que não se baseie em consultas excessivamente complicadas. ou regexes.
Isso fornecerá o resultado desejado:
fonte
Minha idéia é implementar uma função armazenada como esta:
Sinto muito, mas em alguns casos (para um conjunto muito grande), o Oracle pode retornar este erro:
mas acho que esse é um bom ponto de partida;)
fonte
LISTAGG
função personalizada ; eles estavam tentando explicitamente ver se conseguiam encontrar uma maneira eficiente de fazer isso usando aLISTAGG
função interna disponível na versão 11.2.Tente este:
O problema com outras soluções possíveis é que não há correlação entre os resultados da coluna 1 e da coluna 2. Para contornar isso, a consulta interna cria essa correlação e remove as duplicatas desse conjunto de resultados. Quando você faz a lista, o conjunto de resultados já está limpo. o problema tinha mais a ver com a obtenção dos dados em um formato utilizável.
fonte
O SQL foi projetado como linguagem simples, muito próxima do inglês. Então, por que você não escreve como em inglês?
fonte
fonte
SELECT Num1, ( SELECT LISTAGG(Num2) WITHIN GROUP (ORDER BY Num2) FROM (SELECT distinct Num2 FROM listAggTest) ) Num2 FROM ListAggTest;
A solução mais eficaz é SELECT interna com GROUP BY, porque DISTINCT e expressões regulares são lentas como o inferno.
Essa solução é bem simples - primeiro você obtém todas as combinações únicas de num1 e num2 (SELECT interno) e, em seguida, obtém a sequência de todos os num2 agrupados por num1.
fonte
SELECT * FROM ListAggTest;
.