Est-ce que T-SQL a une fonction d'agrégation pour concaténer les strings?

Duplicats possibles:
Implode type fonction dans SQL Server 2000?
Concaténer les valeurs de ligne T-SQL

J'ai une vue que j'interroge qui ressemble à ceci:

BuildingName PollNumber ------------ ---------- Foo Centre 12 Foo Centre 13 Foo Centre 14 Bar Hall 15 Bar Hall 16 Baz School 17 

J'ai besoin d'écrire une requête qui regroupe BuildingNames et affiche une list de PollNumbers comme ceci:

 BuildingName PollNumbers ------------ ----------- Foo Centre 12, 13, 14 Bar Hall 15, 16 Baz School 17 

Comment puis-je faire cela dans T-SQL? Je préférerais ne pas avoir à écrire une procédure stockée pour cela, car cela semble être une surcharge, mais je ne suis pas exactement une personne de la database. Il semble qu'une fonction agrégée comme SUM () ou AVG () soit ce dont j'ai besoin, mais je ne sais pas si T-SQL en a une. J'utilise SQL Server 2005.

    non, pour SQL Server 2005 et plus, vous devez faire quelque chose comme ceci:

     --Concatenation with FOR XML and eleminating control/encoded character expansion "& < >" set nocount on; declare @YourTable table (RowID int, HeaderValue int, ChildValue varchar(5)) insert into @YourTable VALUES (1,1,'CCC') insert into @YourTable VALUES (2,2,'B<&>B') insert into @YourTable VALUES (3,2,'AAA') insert into @YourTable VALUES (4,3,'<br>') insert into @YourTable VALUES (5,3,'A & Z') set nocount off SELECT t1.HeaderValue ,STUFF( (SELECT ', ' + t2.ChildValue FROM @YourTable t2 WHERE t1.HeaderValue=t2.HeaderValue ORDER BY t2.ChildValue FOR XML PATH(''), TYPE ).value('.','varchar(max)') ,1,2, '' ) AS ChildValues FROM @YourTable t1 GROUP BY t1.HeaderValue 

    SORTIE:

     HeaderValue ChildValues ----------- ------------------- 1 CCC 2 AAA, B<&>B 3 <br>, A & Z (3 row(s) affected) 

    Aussi, faites attention, toutes FOR XML PATH concaténations FOR XML PATH gèreront pas correctement les caractères spéciaux XML comme mon exemple ci-dessus.

    Il n'y a pas de fonction embeddede dans Sql Server, mais cela peut être réalisé en écrivant un agrégat défini par l'user. Cet article mentionne une telle fonction dans le cadre des exemples SQL Server: http://msdn.microsoft.com/en-us/library/ms182741.aspx

    A titre d'exemple, j'inclus le code pour un agrégat de concaténation. Pour l'utiliser, créez un projet de database dans Visual Studio, ajoutez un nouveau SqlAggregate et remplacez le code par l'exemple ci-dessous. Une fois déployé, vous devriez find un nouvel assemblage dans votre database et une fonction d'agrégat Concatenate

     using System; using System.Data.SqlTypes; using System.IO; using System.Text; using Microsoft.SqlServer.Server; [Serializable] [SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToNulls = true, IsInvariantToDuplicates = false, IsInvariantToOrder = false, MaxByteSize = 8000, Name = "Concatenate")] public class Concatenate : IBinarySerialize { private SsortingngBuilder _intermediateResult; internal ssortingng IntermediateResult { get { return _intermediateResult.ToSsortingng(); } } public void Init() { _intermediateResult = new SsortingngBuilder(); } public void Accumulate(SqlSsortingng value) { if (value.IsNull) return; _intermediateResult.Append(value.Value); } public void Merge(Concatenate other) { if (null == other) return; _intermediateResult.Append(other._intermediateResult); } public SqlSsortingng Terminate() { var output = ssortingng.Empty; if (_intermediateResult != null && _intermediateResult.Length > 0) output = _intermediateResult.ToSsortingng(0, _intermediateResult.Length - 1); return new SqlSsortingng(output); } public void Read(BinaryReader reader) { if (reader == null) throw new ArgumentNullException("reader"); _intermediateResult = new SsortingngBuilder(reader.ReadSsortingng()); } public void Write(BinaryWriter writer) { if (writer == null) throw new ArgumentNullException("writer"); writer.Write(_intermediateResult.ToSsortingng()); } } 

    Pour l'utiliser, vous pouvez simplement écrire une requête agrégée:

     create table test( id int identity(1,1) not null primary key , class tinyint not null , name nvarchar(120) not null ) insert into test values (1, N'This'), (1, N'is'), (1, N'just'), (1, N'a'), (1, N'test'), (2, N','), (3, N'do'), (3, N'not'), (3, N'be'), (3, N'alarmed'), (3, N','), (3, N'this'), (3, N'is'), (3, N'just'), (3, N'a'), (3, N'test') select dbo.Concatenate(name + ' ') from test group by class drop table test 

    La sortie de la requête est:

     -- Output -- =================== -- This is just a test -- , -- do not be alarmed , this is just a test 

    J'ai emballé la class et l'agrégat comme un script que vous pouvez find ici: https://gist.github.com/FilipDeVos/5b7b4addea1812067b09