U-SQLでヒストグラムを作ろうとする場合、データポイントをBINごとに仕分けて、集計ということになります。
これは直接サポートされていないので、色々ステップを踏む必要がありました。
BINに仕分ける部分は、U-SQLで書けなくは無いようにも思うのですが、SWITCHとか使うのは嫌ですし、使うたびにコードを埋め込まないといけないので、クエリーが醜くなりそう。
ラムダ式をU-SQL変数に(名前付きラムダ)
今年出た機能のうち、U-SQL Spring 2018 Release Notes に書いてある、以下を使うと、C#関数を、変数に入れてインラインで手軽に使えるようになります。(コードビハインドやアセンブリ登録がいらない!!)
U-SQL adds C# Func<>-typed variables in DECLARE statements (named lambdas)
TVFやPROCEDUREに比べて、引数も自由だし、単純なROW-wideな関数を定義するには楽です。本当にインラインにしちゃうと、再利用できないし。
DECLARE @cbin = new SQL.ARRAY<double>{0,1000,20000};
DECLARE @binning Func<double,SqlArray<double>,double> =
(n,bin) => {
if(n < bin[0]) return double.NegativeInfinity;
if(n >= bin[2]) return double.PositiveInfinity;
return ((Math.Floor((n - bin[0]) / bin[1]) + 1) * bin[1]);
@hoge2 =
SELECT @binning(value, @bin) AS newValue
FROM @a;
release note を読むと、以下のようにパッケージに登録して再利用も容易になるようです。
DROP PACKAGE IF EXISTS MyFunctions;
CREATE PACKAGE MyFunctions () AS
BEGIN
EXPORT @EnumerateToFloor Func<int,double,IEnumerable<int>> =
(x, y) => Enumerable.Range(x, (int) Math.Floor(y));
EXPORT @TryParseDateTime Func<string, DateTime?> =
(d) => {
DateTime dt;
var b = DateTime.TryParse(d, out dt);
return b ? (DateTime?) dt : (DateTime?) null;
};
END;
さらに、ラムダ同士で呼び合ったりすることも可能。
U-SQLでは、関数のようにパラメータ化された処理を使うことが難しかったのですが、これでインラインのROW-WIDEな処理は少なくともすっきりかけるようになりますね。