Soci (Soczó Zsolt) szakmai blogja

2008.02.29.

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

Filed under: Adatbázisok,SQL Server 2008,Szakmai élet — Soczó Zsolt @ 16:22

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.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress