Mysql
如何創建使用者定義的聚合函式?
我需要一個 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)
根據文件http://dev.mysql.com/doc/refman/5.5/en/adding-udf.html只能用 C 編寫聚合函式。對不起!
我不知道是否有辦法定義一個新的聚合函式,而不是弄亂 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測試**