sql >> Database teknologi >  >> RDS >> Sqlserver

Udjævn tilknytningstabel til kolonne med flere værdier?

Jeg oprettede en CLR-aggregatfunktion der tager en varchar kolonne og returnerer alle dens værdier adskilt af kommaer. Med andre ord forbinder den flere strenge til en kommasepareret liste. Jeg er sikker på, at dens ydeevne er langt bedre end noget T-Sql-trick .

Som enhver aggregeret funktion kan den bruges i kombination med group by . For eksempel:

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

Her er C#-koden til at oprette CLR-samlingen i SQL Server 2008:

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);
    }
}

Her er koden til at oprette funktionen (selvom implementering fra Visual Studio bør gøre det automatisk):

CREATE AGGREGATE [dbo].[JoinStrings]
(@s [nvarchar](4000))
RETURNS[nvarchar](max)
EXTERNAL NAME [YouAssemblyName].[JoinStrings]


  1. MySQL:Langsom log; tilføje CPU-brug

  2. Angiver primær/standardpost i databasen

  3. Hvordan specificerer du IN-sætning i en dynamisk forespørgsel ved hjælp af en variabel?

  4. Vedvarende login PHP og SQL