<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>SQLServer関連</title><link>http://blogs.wankuma.com/ganfield/category/1881.aspx</link><description>SQL Server関連の話題</description><managingEditor>がんふぃーるど(ganfield@wankuma.com)</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ウィンドウ関数（分析関数） - SQL Server 2005</title><link>http://blogs.wankuma.com/ganfield/archive/2008/07/31/151200.aspx</link><pubDate>Thu, 31 Jul 2008 00:57:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2008/07/31/151200.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/151200.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2008/07/31/151200.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/151200.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/151200.aspx</trackback:ping><description>&lt;p&gt;WNDPROCとかじゃアｒ （ｒｙ&lt;/p&gt; &lt;p&gt;ウィンドウ関数はSQL Serverでも使用できます。なんてったって標準SQLですから。&lt;/p&gt; &lt;h2&gt;ウィンドウ関数を使ってみる&lt;/h2&gt; &lt;p&gt;SQL Server 2005のAdventureWorksを使用して、ウィンドウ関数を使ってみます。やりたいことは&lt;a href="http://blogs.wankuma.com/ganfield/archive/2008/07/29/150723.aspx"&gt;Oracle版&lt;/a&gt;と同じようなことですが、部署IDみたいなものが無かったので性別でウィンドウを区切ってみます。&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Employeeテーブルの中で、性別ごとに生年月日順にランク付けする。&lt;/li&gt; &lt;li&gt;ランク付けしたら、同じ性別の中で何人中何位だったかわかるようにする。&lt;/li&gt; &lt;li&gt;取得する項目はEmployeeID, 性別, 順位, 性別ごとの人数&lt;/li&gt;&lt;/ul&gt; &lt;table cellspacing="0" cellpadding="2" width="800" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="800"&gt; &lt;p&gt;SELECT&lt;br&gt; a.EmployeeID as 社員ID,&lt;br&gt; a.Gender as 性別,&lt;br&gt; Rank() OVER (PARTITION BY a.Gender ORDER BY a.BirthDate) as 順位,&lt;br&gt; Count(a.Gender) OVER (PARTITION BY a.Gender) as 人数&lt;br&gt;FROM&lt;br&gt; HumanResources.Employee a&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Oracleと同じですね。実行計画は次の通り&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="800" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="800"&gt; &lt;p&gt;|--Nested Loops(Inner Join)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Table Spool&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Segment&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Sequence Project(DEFINE:([Expr1002]=rank))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Segment&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Segment&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Sort(ORDER BY:([a].[Gender] ASC, [a].[BirthDate] ASC))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Clustered Index Scan(OBJECT:([AdventureWorks].[HumanResources].[Employee].[PK_...] AS [a]))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Nested Loops(Inner Join, WHERE:((1)))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1007],0)))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Stream Aggregate(DEFINE:([Expr1007]=Count(*)))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Table Spool&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |--Table Spool&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;strong&gt;参考文献&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/library/ms189461.aspx"&gt;SQL Server 2005 Books Online - OVER句&lt;/a&gt;&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/151200.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ユーザー定義集計関数：CSV形式で文字列を集計 - SQL Server 2005</title><link>http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx</link><pubDate>Mon, 30 Jun 2008 01:12:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/146270.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2008/06/30/146270.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/146270.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/146270.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://blogs.wankuma.com/ganfield/archive/2008/06/22/144865.aspx"&gt;前回&lt;/A&gt;のOracleでユーザ定義集計関数を作成したので、今度はSQL Server 2005で作ってみた。ちなみに、わんくま内のblogを検索してみたらSQL CLRについてのエントリがあまり無い。&lt;/P&gt;
&lt;P&gt;人気茄子&amp;#8230;やろうと思えばDataTableでガリガリやれないこともない&amp;#8230;&lt;/P&gt;
&lt;P&gt;&amp;#8230;&lt;/P&gt;
&lt;P&gt;まあ、これからですよ！これから！ははは&lt;/P&gt;
&lt;P&gt;気を取り直して、SQL CLRで作るユーザ定義集計関数。いってみよー&lt;/P&gt;
&lt;H2&gt;大まかな流れ&lt;/H2&gt;
&lt;P&gt;Oracleの場合と違い、SQL Serverでユーザ定義集計関数を作成する場合、アセンブリを作成する必要がのですが&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;.NETでコーディングしてアセンブリ作成（署名忘れずに※１） 
&lt;LI&gt;1で作成したクラスを紐付けたユーザー定義集計関数を定義&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;と、あまり変わらないじゃん♪　（え？アセンブリを署名するのが面倒？まあ、やらないでもいい方法があるんで♪）&lt;/P&gt;
&lt;H2&gt;ユーザー定義集計関数インターフェース&lt;/H2&gt;
&lt;P&gt;インターフェースというと語弊が若干あるのですが、要する実装する必要があるインターフェース＆定義する必要のあるメソッド及びアトリビュートです。&lt;/P&gt;
&lt;P&gt;クラスに対して必要なもの&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Microsoft.SqlServer.Server.SqlUserDefinedAggregate アトリビュート（クラス）の定義 
&lt;LI&gt;Microsoft.SqlServer.Server.IBinarySerialize インターフェースの継承&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;メンバに対して必要なもの&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;public void Init() 
&lt;LI&gt;public void Accumulate(SqlString value) 
&lt;LI&gt;public void Merge(CsvConcatenation other) 
&lt;LI&gt;public SqlString Terminate() 
&lt;LI&gt;public void Read(BinaryReader r)　※IBinarySerializeの実装 
&lt;LI&gt;public void Write(BinaryWriter w)　※IBinarySerializeの実装&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;うム。上の四つはOracleと一緒だ（笑&lt;/P&gt;
&lt;P&gt;ということで、サクサクいきましょう。&lt;/P&gt;
&lt;H2&gt;CsvConcate集計関数&lt;/H2&gt;
&lt;P&gt;こういう、関数の実装部分を定義するクラスの名前っていつも悩みますね。動詞にするかしないかってことで。今回はSQL Server 2005に登録する関数と同じ名前にしたかったので、CsvConcateにしましたが、クラス名だけならCsvConcatenationにしちゃってもいいんですよね。&lt;/P&gt;
&lt;P&gt;とまあ、クラス名の話はさておき、文字列をCSV形式で集計してくれるユーザー定義集計関数を作りたいと思います。&lt;/P&gt;
&lt;P&gt;まずはMicrosoft.SqlServer.Server.SqlUserDefinedAggregate アトリビュートの定義&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=715 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=713&gt;
&lt;P&gt;[Serializable]&lt;BR&gt;[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Microsoft.SqlServer.Server.Format.UserDefined, //シリアライズ形式（ネイティブかユーザ定義）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsInvariantToNulls = true,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // NULLに対して不変かどうか（NULLを集計しない場合はTrue）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsInvariantToDuplicates = false,&amp;nbsp;&amp;nbsp;&amp;nbsp; // 重複値に対して不変かどうか（重複した値を集計しない場合はTrue）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsInvariantToOrder = false,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 現在は未使用（未実装）&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MaxByteSize = 8000)]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // MAXサイズ&lt;BR&gt;public class CsvConcate : Microsoft.SqlServer.Server.IBinarySerialize&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;定義の内容はコメントの通り。NULLや重複値については用途に合わせて使い分けて下さい。&lt;/P&gt;
&lt;P&gt;次はInit～Treminateまでのメソッドです。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=717 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=715&gt;
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 中間結果を保持&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;private StringBuilder intermediateResult; 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 初期化&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;public void Init()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult = new StringBuilder();&lt;BR&gt;} 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 実際の集計処理&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;/// &amp;lt;param name="value"&amp;gt;&amp;lt;/param&amp;gt;&lt;BR&gt;public void Accumulate(SqlString value)&lt;BR&gt;{ 
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (value.IsNull)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult.Append(string.Empty).Append(',');&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult.Append(value.Value).Append(','); 
&lt;P&gt;} 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 部分計算された場合のマージ&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;/// &amp;lt;param name="other"&amp;gt;&amp;lt;/param&amp;gt;&lt;BR&gt;public void Merge(CsvConcate other)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult.Append(other.intermediateResult);&lt;BR&gt;} 
&lt;P&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// 終了処理&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;BR&gt;public SqlString Terminate()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; string output = string.Empty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 最後のカンマはおさらば&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (intermediateResult != null &amp;amp;&amp;amp; intermediateResult.Length &amp;gt; 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output = intermediateResult.ToString(0, intermediateResult.Length - 1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new SqlString(output);&lt;BR&gt;}&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;そんでもってIBinarySerialize インターフェースの実装(Microsoft.SqlServer.Server.Format.Nativeの場合は必要なし？)&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=710 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=708&gt;
&lt;P&gt;#region IBinarySerialize メンバ 
&lt;P&gt;void IBinarySerialize.Read(BinaryReader r)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (r == null) throw new ArgumentNullException("r");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; intermediateResult = new StringBuilder(r.ReadString());&lt;BR&gt;} 
&lt;P&gt;void IBinarySerialize.Write(BinaryWriter w)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (w == null) throw new ArgumentNullException("w");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; w.Write(intermediateResult.ToString());&lt;BR&gt;} 
&lt;P&gt;#endregion&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;アセンブリを署名するのを忘れずに（キーペアは「sn」などで作成しましょう）※１&lt;/P&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;ユーザー定義集計関数の登録&lt;/H2&gt;
&lt;P&gt;さて、署名付きのアセンブリが作成できたのなら、あとは登録するだけです。とりあえず、やることは三つ&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;アセンブリの登録 
&lt;LI&gt;ユーザー定義集計関数の定義（クラスとの紐付け）&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;登録するアセンブリの配置場所ですが、こいつは適当「UserLib」に切っておいて、そこに作成したアセンブリ「StringUtility.dll」を配置します。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=706 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=704&gt;C:\Program Files\Microsoft SQL Server\90\UserLib\StringUtility.dll&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;（別にSQL Serverと同じフォルダでなくても構いません。）&lt;/P&gt;
&lt;P&gt;それと、CLR統合機能を予め有効化する必要があるので、以下のSQLを発行(参考文献：夏椰さんのを参照）&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=700 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=700&gt;sp_configure 'clr enabled', 1&lt;BR&gt;GO&lt;BR&gt;RECONFIGURE&lt;BR&gt;GO&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;あとはこいつを登録してやるだけです。以下のSQLを発行&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=700 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=700&gt;
&lt;P&gt;-- アセンブリのパス&lt;BR&gt;declare @asmblyPath nvarchar(1000)&lt;BR&gt;set @asmblyPath = 'C:\Program Files\Microsoft SQL Server\90\UserLib\StringUtility.dll' 
&lt;P&gt;-- アセンブリの登録&lt;BR&gt;CREATE ASSEMBLY StringUtility FROM @asmblyPath&lt;BR&gt;WITH permission_set=Safe;&lt;BR&gt;GO 
&lt;P&gt;-- ユーザー定義集計関数の定義&lt;BR&gt;CREATE AGGREGATE Concatenate(@input nvarchar(4000))&lt;BR&gt;RETURNS nvarchar(4000)&lt;BR&gt;EXTERNAL NAME [StringUtility].[Wankuma.Ganf.SqlClr.StringUtility.CsvConcate];&lt;BR&gt;GO&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;これで、完成。では実際にNorthWindで使ってみましょう。（AdventureWorksでもいいですが、あれは結構件数が入っているので、バッファがすぐにあふry）&lt;/P&gt;
&lt;H2&gt;使い方&lt;/H2&gt;
&lt;P&gt;こちらも、Oracle同様、他の集計関数と同じ使い方です。&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=2 width=700 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=700&gt;
&lt;P&gt;select country, dbo.csvconcate(employeeid) &lt;BR&gt;from employees group by country&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;H2&gt;&lt;/H2&gt;
&lt;H2&gt;参考文献&lt;/H2&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/ja-jp/library/ms131051.aspx"&gt;MSDN CLR ユーザー定義集計の要件&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title=http://technet.microsoft.com/ja-jp/library/ms161551.aspx href="http://technet.microsoft.com/ja-jp/library/ms161551.aspx"&gt;http://technet.microsoft.com/ja-jp/library/ms161551.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;ユーザー定義集計関とは違いますが、数夏椰さんのとこでいくつかSQL CLRが公開されています。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://kaya.wankuma.com/box/Default.aspx"&gt;夏椰の庵 - Secluded Spot of Kaya - BOX&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;※１　アセンブリの署名を行わなくても、アセンブリの登録は可能です。その場合は、データベースのTRUSTWORTHYをONにしましょう。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/146270.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>