将关联表展平为多值列?

Tru*_*an1 2 sql t-sql sql-server sql-server-2008

我有一个只有产品ID和类别ID的表(产品可以在多个类别中).如何将类别ID展平到产品列中,以便我以此结束:

id | name | desc | categories
1 | test1 | lorem | 1,3,4,23
2 | test2 | ipsom | 4,6,24
Run Code Online (Sandbox Code Playgroud)

这就像我需要循环到categories列的单独表中.我怎么能这样做或者有更好的方法吗?

Die*_*ego 7

我创建了一个CLR聚合函数,它接受一个varchar列并返回以逗号分隔的所有值.换句话说,它将几个字符串连接到以逗号分隔的列表中.我相信它的性能比任何T-Sql技巧都好.

作为任何聚合函数,它可以与之结合使用group by.例如:

SELECT id, name, desc, JoinStrings(CONVERT(VARCHAR(20), category_id))
FROM product p
INNER JOIN category_products c ON p.category_id = c.category_id
GROUP BY id, name, desc
Run Code Online (Sandbox Code Playgroud)

这是在Cql Server 2008中创建CLR程序集的C#代码:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;


[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToDuplicates=false, IsInvariantToOrder=false, IsInvariantToNulls=true, MaxByteSize=-1)]
public struct JoinStrings : IBinarySerialize
{
    private char[] sb;
    private int pos;
    public void Init()
    {
        sb = new char[512000];
        pos = 0;
    }

    public void Accumulate(SqlString Value)
    {
        if (Value.IsNull) return;
        char[] src = Value.ToString().ToCharArray();
        Array.Copy(src, 0, sb, pos, src.Length);
        pos += src.Length;
        sb[pos] = ',';
        pos++;
    }

    public void Merge(JoinStrings Group)
    {
        Accumulate(Group.Terminate());
    }

    public SqlString Terminate()
    {
        if (pos <= 0) 
            return new SqlString();
        else
            return new SqlString(new String(sb, 0, pos-1));
    }

    public void Read(System.IO.BinaryReader r)
    {
        this.Init();
        pos = r.ReadInt32();
        r.Read(sb, 0, pos);
    }

    public void Write(System.IO.BinaryWriter w)
    {
        w.Write(pos);
        w.Write(sb, 0, pos);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是创建函数的代码(虽然从Visual Studio部署应该自动执行):

CREATE AGGREGATE [dbo].[JoinStrings]
(@s [nvarchar](4000))
RETURNS[nvarchar](max)
EXTERNAL NAME [YouAssemblyName].[JoinStrings]
Run Code Online (Sandbox Code Playgroud)