Mat*_*ick 9 mysql aggregate functions
我需要一个 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)
Run Code Online (Sandbox Code Playgroud)
ype*_*eᵀᴹ 10
我不知道是否有办法定义一个新的聚合函数,而不是弄乱 MySQL 源代码。
但是如果你的数字都是正数,你很可能从算术恒等式中推导出来:
log( product( Ai ) ) = sum( log( Ai ) )
Run Code Online (Sandbox Code Playgroud)
您可以使用它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 ;
Run Code Online (Sandbox Code Playgroud)
当数据可以有 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 ;
Run Code Online (Sandbox Code Playgroud)
在SQL-Fiddle测试
对于其他没有 MySQL 将布尔值自动转换为整数的 DBMS,
(NOT EXISTS (SELECT ...))
Run Code Online (Sandbox Code Playgroud)
应替换为:
(CASE WHEN EXISTS (SELECT 1...) THEN 0 ELSE 1 END)
Run Code Online (Sandbox Code Playgroud)
专门针对Oracle,需要多做一些改动,不改变答案的逻辑,只是因为Oracle在某些方面没有遵循严格的ANSI标准。在SQL-Fiddle-2测试
为了学习钓鱼,我已经成功编译安装了一个“Hello, World!” 在这里找到MySQL 的 UDF(用户定义函数)。hello_world.so 文件(编译后gcc -shared -o hello_world.so -I /usr/include/mysql hello_world.c)应存放在/usr/lib/mysql/plugins/ 中,Ubuntu linux 系统755 权限。[“-I /usr/include/mysql”是mysql头文件的路径;我发现如果没有这个参数,我的代码将无法编译,但是 YMMV。]
该程序除了打印出字符串“Hello, World!”之外什么都不做。对于查询结果数据集中的每条记录,但这就是它应该做的。我会在接下来的几天里尝试写一个 SMALL 聚合函数。有一个聚合函数的例子,它计算一组价格和数量记录的平均成本;SMALL 函数最终不应该与那个函数有什么不同。
希望这可以帮助。