読者です 読者をやめる 読者になる 読者になる

SQL に FOLD があれば・・・

SQL 妄想

便利だと思うんだ*1 *2
例えば、

-- 総積を求める
SELECT n.FOLD(*, 1) FROM SomeTable;
-- 文字列を全部結合
SELECT str.FOLD(||, '') FROM SomeTable;

みたいな。
第二引数を省略すると一番最初の要素が使われる*3とかすると、上の例は

-- 総積を求める
SELECT n.FOLD(*) FROM SomeTable;
-- 文字列を全部結合
SELECT str.FOLD(||) FROM SomeTable;

みたいに書けたりとか*4 *5
更に更に、無名関数とかでっち上げてみたり。

-- カンマ区切りの文字列にする
SELECT
    COALESCE(str.FOLD({$1 || ', ' || $2}), '')
FROM
    SomeTable
;

上の例で、波括弧に囲まれた部分が無名関数で、第一引数 ($1) と第二引数 ($2) の間にカンマを挟んで返す関数を定義してる感じ。


無名関数内に無名関数定義するとどっちがどっちの引数か分からなくなるから、そういう時は $1.1 みたいに区別できるとか?
外側から 1, 2, ... とするか、今の関数から近い順に 1, 2, ... とするかは、自分を 0 と考えて自分から近い順に付けるのがいいのかな。で、$0.1 のシンタックスシュガーが $1 みたいな!
そうすれば、外側の関数からの内側の関数の引数へのアクセスが構文上不可能になるし。


・・・以上、実装のじの字も考えてない妄想でした。だってあったら便利そうじゃん!

*1:パフォーマンス?知りません(何

*2:名前は別に REDUCE でも INJECT でも良かったんだけど、やっぱり短いほうがいいよね、ってことで FOLD

*3:省略時にできる限り自然になるように、Java とかのメソッド呼び出し風の構文にしてる

*4:対象 (SomeTable) が空の場合の挙動が上 (初期値あり) と下 (初期値省略) では異なる。上は初期値がそのまま返るけど、下は NULL になる

*5:普通の関数型言語なら、対象がリストだろうから head と tail 使えばいいんだろうな。例えば、F# だと、「List.fold_left (fun a b -> a + ", " + b) L.Head L.Tail;;」とかすればいい。