ユーザー定義の集計関数を作成するにはどうすればよいですか?


8

MySQLが提供していない集約関数が必要です。

MySQLのSQLフレーバー(つまり、Cではない)にしたいのですが。

どうすればよいですか?私が行き詰まっているのは、集約関数を作成することです- ドキュメントは、これがどのように行われるかについて言及していないようです。

product関数の望ましい使用法の例:

mysql> select product(col) as a from `table`;
+------+
| a    |
+------+
|  144 |
+------+
1 row in set (0.00 sec)

mysql> select col, product(col) as a from `table` group by col;
+-----+------+
| col | a    |
+-----+------+
|   6 |   36 |
|   4 |    4 |
+-----+------+
2 rows in set (0.01 sec)

回答:


7

ドキュメントhttp://dev.mysql.com/doc/refman/5.5/en/adding-udf.htmlによると、Cでのみ集計関数を記述できます。


CまたはC ++。とにかく、SQLではありません。
Mike Sherrill「Cat Recall」、

1
私は、Cの呼び出し規約を使用して、プラットフォームでサポートされるバイナリ形式でバイナリライブラリを生成できる言語を想定しています。
Colin 't Hart

知りません。それはされた文書、バージョン5.0の「CまたはC ++(またはC呼び出し規約を使用することができます別の言語)」として。ドキュメントは、バージョン5.1で「またはC呼び出し規約を使用できる別の言語」を削除しました。それは落とすべき奇妙なフレーズです。
Mike Sherrill「Cat Recall」、

最近のmysqlバージョンで利用できますか(数年後)?
Dinesh 2017年

9

MySQLのソースコードをいじらないと、新しい集計関数を定義する方法があるかどうかわかりません。

しかし、数値がすべて正であれば、算術的同一性から派生する可能性があります。

log( product( Ai ) ) = sum( log( Ai ) )

EXP(SUM(LOG(x)))計算に使用できますPRODUCT(x)SQL-Fiddleでテストします

SELECT EXP(SUM(LOG(a))) AS product
FROM t ;

SELECT col, EXP(SUM(LOG(a))) AS product
FROM t 
GROUP BY col ;

データに0が含まれる可能性がある場合は、少し複雑になります。

SELECT (NOT EXISTS (SELECT 1 FROM t WHERE a = 0)) 
       * EXP(SUM(LOG(a))) AS p
FROM t 
WHERE a > 0 ;

SELECT d.col, 
       (NOT EXISTS (SELECT 1 FROM t AS ti WHERE ti.col = d.col AND ti.a = 0)) 
       * COALESCE(EXP(SUM(LOG(t.a))),1)  AS p
FROM 
    ( SELECT DISTINCT col
      FROM t
    ) AS d
  LEFT JOIN
    t  ON  t.col = d.col
       AND t.a > 0
GROUP BY d.col ;

SQL-Fiddleでテスト済み


MySQLのブール値の整数への自動変換を持たない他のDBMSの場合、

(NOT EXISTS (SELECT ...))

置き換えられるべきです:

(CASE WHEN EXISTS (SELECT 1...) THEN 0 ELSE 1 END) 

特にOracleの場合、回答のロジックを変更せずに、さらにいくつかの変更が必要になります。これは、Oracleが一部の領域で厳密なANSI標準に従っていないためです。SQL-Fiddle-2でテスト済み


2
それはかわいい。高校の数学は私を悩ませるために戻ってきました。+1 !!!
RolandoMySQLDBA 2012

1
すばらしい数学ですが、実際には、一般的に集計関数を作成する方法を知りたかったのです。 productいくつかの例の1つにすぎませんでした。
Matt Fenwick 2012

これはかなりクールですが、log(0)が未定義であるため、いずれかの値がゼロの場合は機能しません。
jameshfisher 14

@jameshfisher正解。追加の条件を簡単に記述して、ゼロをチェックできます(もちろん、積はゼロになります)。当時はそのような複雑さを追加する必要があるとは思いませんでした。
ypercubeᵀᴹ

その条件を追加するのに最適な方法はわかりません。値の内部関数に条件を追加することはできません。私たちはそれを求めているPRODUCT(..., 0, ...) = 0ので、選択EXP(SUM(..., f(0), ...)) = 0した一部のfものについてそれを求めていますが、これを満たすために、それが必要SUM(..., f(0), ...) = LOG(0)です-log(0)と同じ問題によって再び阻止されます)は未定義です。他の方法でゼロの存在を確認する必要がありMIN(ABS(a)) = 0ます。だから私たちは持っているでしょうSELECT CASE WHEN MIN(ABS(a)) = 0 THEN 0 ELSE EXP(SUM(LOG(a))) END AS product。これはあなたが考えていたようなことですか?
jameshfisher 14

3

釣り方を学ぶために、「Hello、World!」をコンパイルしてインストールしました。MySQLのUDF(ユーザー定義関数)はここにあります。hello_world.soファイル(に準拠した後gcc -shared -o hello_world.so -I /usr/include/mysql hello_world.c)は、Ubuntu linuxシステムでは755権限で/ usr / lib / mysql / plugins /に保存する必要があります。[「-I / usr / include / mysql」は、mysqlヘッダーファイルへのパスです。私のコードは、このパラメーターなしではコンパイルできないが、YMMVであることがわかりました。]

プログラムは文字列「Hello、World!」を出力するだけです。クエリの結果のデータセット内の各レコードに対してですが、それですべてです。今後数日でSMALL集約関数を作成するように努めます。価格と数量のレコードのグループの平均コストを計算する集計関数の例があります。SMALL関数は、最終的にその関数とそれほど異なるものであってはなりません。

お役に立てれば。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.