Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

February 29, 2008 / by Zsolt Soczó

SQL Server 2008 újdonságok 24. – Multi-input user-defined aggregates

Eddig a saját aggregáló függvények csak 1 bemeneti változón dolgozhattak, most ezt a limitet feloldották. Így megírhatjuk magunk azokat a függvényeket, amelyek más termékekben már benne vannak, és amelyek nevét nem mondjuk ki. :)

Példaként mutatok egy Population Covariance számító aggregáló függvényt (a másik termék doksijából vettem a függvény számítási módját, de nem vállalok rá garanciát, hogy jól írtam át CLR UDF-re):

using System;
using System.Data.SqlTypes;
using System.Runtime.InteropServices;
using Microsoft.SqlServer.Server;

[Serializable]
[SqlUserDefinedAggregate(
Format.Native, //use clr serialization to serialize the intermediate result
IsInvariantToNulls = true, //the aggregate of S, {NULL} is the same as aggregate of S
IsInvariantToDuplicates = false, //optimizer property
IsInvariantToOrder = true, //optimizer property
IsNullIfEmpty = true)
]
[StructLayout(LayoutKind.Sequential)]
public class PopulationCovariance
{
    double sumOfA;
    double sumOfB;
    double sumOfAMultB;
    ulong count;

    public void Init()
    {
        sumOfA = sumOfB = sumOfAMultB = 0;
    }

    public void Accumulate(SqlDouble a, SqlDouble b)
    {
        if (a.IsNull || b.IsNull)
        {
            return;
        }

        sumOfA += a.Value;
        sumOfB += b.Value;
        sumOfAMultB += a.Value * b.Value;
        count++;
    }

    public void Merge(PopulationCovariance other)
    {
        sumOfA += other.sumOfA;
        sumOfB += other.sumOfB;
        sumOfAMultB += other.sumOfAMultB;
        count += other.count;
    }

    public SqlDouble Terminate()
    {
        if (count == 0)
        {
            return SqlDouble.Null;
        }

        return (sumOfAMultB - sumOfA * sumOfB / count) / count;
    }
}

Mielőtt bemutatnám a függvény használatát előre bocsájtom, hogy nem értek a statisztikai számításokhoz, de feltételezem a függvény kapcsolatot, összefüggést keres a két halmaz között.

create aggregate PopulationCovariance(@a float, @b float) 
returns float
external name SqlClrTest.PopulationCovariance

if object_id('TestOrder') is not null drop table TestOrder

create table TestOrder
(
  Id int not null primary key identity,
  Discount float,
  OrderedAmount int
)

insert TestOrder (Discount, OrderedAmount)
values 
(0, 5),
(10, 23),
(5, 12),
(2, 1),
(14, 42)

select dbo.PopulationCovariance(Discount, OrderedAmount) from TestOrder

truncate table TestOrder
insert TestOrder (Discount, OrderedAmount)
values 
(10, 5),
(1, 23),
(2, 12),
(20, 1),
(4, 42)

select dbo.PopulationCovariance(Discount, OrderedAmount) from TestOrder

truncate table TestOrder
insert TestOrder (Discount, OrderedAmount)
values 
(10, 5),
(0, 23),
(2, 12),
(5, 1),
(14, 42)

select dbo.PopulationCovariance(Discount, OrderedAmount) from TestOrder
73.08
-65.84
30.48

Az első adathalmaz alapján ha nagy a diszkont értéke, többet vesznek az emberek a termékekből. A másodikban pont fordítva hat a diszkont. A harmadikban próbáltam összezagyválni az adatokat, ott kisebb, de pozitív a két halmaz függése. Valaki megszakértheté nekem ezeket a számokat, hogy jól értelmezem-e? Gondolom valahogyan normalizálni kellene a kimenetet, de nem ismerem a szabályokat.

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.