Estou descobrindo uma maneira de agregar strings de linhas diferentes em uma única linha. Estou procurando fazer isso em muitos lugares diferentes, então ter uma função para facilitar isso seria bom. Eu tentei soluções usando COALESCE
e FOR XML
, mas eles simplesmente não funcionam para mim.
A agregação de strings faria algo assim:
id | Name Result: id | Names
-- - ---- -- - -----
1 | Matt 1 | Matt, Rocks
1 | Rocks 2 | Stylus
2 | Stylus
Eu dei uma olhada nas funções de agregação definidas pelo CLR como um substituto para COALESCE
e FOR XML
, mas aparentemente o SQL Azure não oferece suporte a coisas definidas pelo CLR, o que é uma dor para mim porque eu sei que poder usá-lo resolveria um monte de problemas para mim.
Existe alguma solução alternativa possível ou método igualmente ideal (que pode não ser tão ideal quanto CLR, mas hey , vou pegar o que puder) que eu possa usar para agregar minhas coisas?
for xml
não funciona para você?for xml
um mostra um uso de 25% em termos de desempenho de consulta (grande parte da consulta!)for xml path
consulta. Alguns mais rápidos do que outros. Pode depender dos seus dados, mas os que usamdistinct
é mais lento do que usargroup by
. E se você estiver usando.value('.', nvarchar(max))
para obter os valores concatenados, você deve alterar isso para.value('./text()[1]', nvarchar(max))
Respostas:
SOLUÇÃO
A definição de ideal pode variar, mas veja como concatenar strings de linhas diferentes usando Transact SQL regular, que deve funcionar bem no Azure.
EXPLICAÇÃO
A abordagem se resume em três etapas:
Número as linhas usando
OVER
ePARTITION
de agrupamento e ordenando-os conforme necessário para a concatenação. O resultado éPartitioned
CTE. Mantemos contagens de linhas em cada partição para filtrar os resultados posteriormente.Usando recursiva CTE (
Concatenated
) iterar através dos números de linha (NameNumber
coluna) adicionandoName
valores àFullName
coluna.Filtre todos os resultados, exceto aqueles com o maior valor
NameNumber
.Lembre-se de que, para tornar essa consulta previsível, é necessário definir o agrupamento (por exemplo, em seu cenário, as linhas com as mesmas
ID
são concatenadas) e a classificação (presumi que você simplesmente classifique a string alfabeticamente antes da concatenação).Testei rapidamente a solução no SQL Server 2012 com os seguintes dados:
O resultado da consulta:
fonte
Os métodos que usam FOR XML PATH como a seguir são realmente lentos? Itzik Ben-Gan escreve que esse método tem um bom desempenho em seu livro T-SQL Querying (o Sr. Ben-Gan é uma fonte confiável, na minha opinião).
fonte
id
coluna assim que o tamanho da tabela se tornar um problema.&
alternado para&
e assim por diante). Umafor xml
solução mais correta é fornecida aqui .Para aqueles de nós que encontraram este
e não estão usando o Banco de Dados SQL do Azure:STRING_AGG()
em PostgreSQL, SQL Server 2017 e Azure SQLhttps://www.postgresql.org/docs/current/static/functions-aggregate.html
https://docs.microsoft.com/en-us/sql/t-sql/ funções / string-agg-transact-sql
GROUP_CONCAT()
no MySQLhttp://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
(Agradecimentos a @Brianjorden e @milanio pela atualização do Azure)
Código de exemplo:
SQL Fiddle: http://sqlfiddle.com/#!18/89251/1
fonte
STRING_AGG
foi adiado para 2017. Não está disponível em 2016.Embora @serge a resposta esteja correta, comparei o consumo de tempo dele com o xmlpath e descobri que o xmlpath é muito mais rápido. Vou escrever o código de comparação e você pode verificar por si mesmo. Este é o jeito @serge:
E esta é a maneira xmlpath:
fonte
Atualização: Ms SQL Server 2017+, Banco de Dados SQL do Azure
Você pode usar:
STRING_AGG
.O uso é muito simples para a solicitação do OP:
consulte Mais informação
Bem, minha antiga não resposta foi excluída por direito (deixada intacta abaixo), mas se acontecer de alguém pousar aqui no futuro, temos boas notícias. Eles implementaram STRING_AGG () no Banco de Dados SQL do Azure também. Isso deve fornecer a funcionalidade exata originalmente solicitada nesta postagem com suporte nativo e integrado. @hrobky mencionou isso anteriormente como um recurso do SQL Server 2016 na época.
--- Postagem antiga: Não há reputação suficiente aqui para responder a @hrobky diretamente, mas STRING_AGG parece ótimo, no entanto, está disponível apenas no SQL Server 2016 vNext atualmente. Esperançosamente, isso seguirá para o Azure SQL Datababse em breve.
fonte
STRING_AGG()
está declarado para estar disponível no SQL Server 2017, em qualquer nível de compatibilidade. docs.microsoft.com/en-us/sql/t-sql/functions/…Você pode usar + = para concatenar strings, por exemplo:
se você selecionar @test, ele fornecerá todos os nomes concatenados
fonte
select @test += name + ', ' from names
ORDER BY
em sua consulta. Você deve usar uma das alternativas listadas.Achei a resposta de Serge muito promissora, mas também encontrei problemas de desempenho com a escrita. No entanto, quando eu o reestruturei para usar tabelas temporárias e não incluir tabelas CTE duplas, o desempenho foi de 1 minuto e 40 segundos para sub-segundos para 1000 registros combinados. Aqui, é para quem precisa fazer isso sem FOR XML em versões anteriores do SQL Server:
fonte