LoginSignup
0
0

More than 5 years have passed since last update.

U-SQL でヒストグラムを作りたい時のラムダ式

Posted at

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な処理は少なくともすっきりかけるようになりますね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0