在 Oracle 和 MySQL 中,我如何创建一个函数,该函数采用无限数量的参数,以便可以像 GREATEST(value1,value2,...) 那样调用它?
按特定标准比较两个值非常容易,但将“更大”的值传递给另一个比较是我在 SQL 中似乎无法做到的。
谢谢!
编辑(在下面 Mike 的评论之后): 我正在寻找比较多列的解决方案。具体而言,我的问题是如何将 GREATEST() 实现为 UDF。以下代码比较三列。
SELECT CASE WHEN CASE WHEN col_1 < col_2 THEN col_2
ELSE col_1 END < col_3 THEN col_3
ELSE CASE WHEN col_1 < col_2 THEN col_2
ELSE col_1 END END AS greatest
FROM figures;
显然,这并不能很好地扩展。拥有一个将相同比较方法反复应用于值列表的通用函数会更有用。
SQL 我指的是任何 SQL 数据库产品,但我更喜欢在 Oracle 或 MySQL 中运行的解决方案
最佳答案
在 Oracle 中(支持 unpivot 的实例)
SELECT MyID, MAX(GreatestVal)
FROM figures
UNPIVOT (
GreatestVal
FOR MyID
IN (col_1, col_2, col_3,...)
);
Oracle 查询未经测试,因为我手头没有实例 关于 unpivot 的更多详细信息是 located here它与 SQL Server unpivot 做同样的事情。
MySQL 我不确定如何在 MySQL 中执行此操作,但可能会在有机会时进行调查(除非有人击败我。;-))
以下是 SQL Server 的回答:
在 UDF 中这样做并不好,因为在每种情况下都需要所有输入参数。如果您可以将其实现为存储过程,那么您可以为输入参数指定默认值并使用动态列数调用它。无论哪种方式,您都必须决定输入参数的最大数量。下面是 SQL Server 上的 UDF 示例:
SELECT dbo.GREATESTof3(col_1, col_2, col_3)
FROM figures;
CREATE FUNCTION GREATESTof3(@col_1 sql_variant = null, @col_2 sql_variant = null, @col_3 sql_variant = null)
RETURNS sql_variant
AS
BEGIN
DECLARE @GreatestVal sql_variant
DECLARE @ColumnVals TABLE (Candidate sql_variant)
INSERT INTO @ColumnVals
SELECT @col_1
UNION ALL
SELECT @col_2
UNION ALL
SELECT @col_3
SELECT @GreatestVal = MAX(Candidate)
FROM @ColumnVals
RETURN @GreatestVal
END
这将需要为输入参数数量的每个变体创建一个新的 UDF,或者创建一个可以采用更大数量的 UDF,但随后在调用 UDF 时,您必须为每个未使用的参数(空)指定一些值或指定默认值。
备选方案:
这会为您提供整个表中三列的最大值,并且使用动态列数会更容易:
SELECT MAX([Value]) AS Greatest
FROM figures
UNPIVOT
(
[Value]
FOR ColumnName IN ([Col_1], [Col_2], [Col_3])
) AS unpvt
假设您在输出中有一些 rowid 或其他列,以便您可以从每一行的指定列中获得最大的 yield ,您可以这样做:
SELECT RowID, MAX([Value]) AS Greatest
FROM figures
UNPIVOT
(
[Value]
FOR ColumnName IN ([Col_1], [Col_2], [Col_3])
) AS unpvt
GROUP BY RowID
关于mysql - SQL 用户定义函数的参数数量不定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8120236/