In Oracle and MySQL, how can I create a function that takes an indefinite number of parameters so that it may be called like GREATEST(value1,value2,...)?
Comparing two values by a certain standard is pretty easy but passing the "greater" value to yet another comparison is what I don't seem to get work in SQL.
Thanks!
Edit (after Mike's comment below): I am looking for a solution for comparing multiple columns. In concrete terms, my question is how to implement GREATEST() as a UDF. The following code compares three columns.
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;
Apparently, this does not scale so well. It'll be much more useful to have a general function that applies the same comparison method over and over to a list of values.
By SQL I mean any SQL database product but I prefer a solution that works in Oracle or MySQL
In Oracle (instances that support unpivot)
SELECT MyID, MAX(GreatestVal)
FROM figures
UNPIVOT (
GreatestVal
FOR MyID
IN (col_1, col_2, col_3,...)
);
Oracle query is untested because I don't have an instance handy Further details on unpivot are located here and it does the same thing as the SQL Server unpivot.
MySQL I'm unsure of how to do this in MySQL but may investigate as I have opportunity (unless someone beats me to it. ;-) )
The following are SQL Server answers:
Doing it in a UDF is not pretty because all of the input parameters would be REQUIRED in every case. If you could get away with implementing it as a stored procedure then you could specify default values for the input parameters and call it with a dynamic number of columns. Either way, you'll have to decide on a maximum number of input parameters. Here is an example in UDF on SQL Server:
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
This would require a new UDF for each variant of the number of input parameters OR creating one that could take a greater number but then in the call to the UDF you would have to either specify some value for each unused parameter (null) or specify default.
Alternatives:
This gives you the max value of the three columns from the whole table and would be easier to have a dynamic number of columns:
SELECT MAX([Value]) AS Greatest
FROM figures
UNPIVOT
(
[Value]
FOR ColumnName IN ([Col_1], [Col_2], [Col_3])
) AS unpvt
Assuming you have some rowid or another column that you would want in the output so that you could get the greatest from the specified columns for each row you could do something like this:
SELECT RowID, MAX([Value]) AS Greatest
FROM figures
UNPIVOT
(
[Value]
FOR ColumnName IN ([Col_1], [Col_2], [Col_3])
) AS unpvt
GROUP BY RowID
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With