Is there a 'greatest' function in db2? - sql

I found in MYSQL and apparently other database engines that there is a "greatest" function that can be used like: greatest(1, 2, 3, 4), and it would return 4. I need this, but I am using IBM's DB2. Does anybody know of such an equivalent function, even if it only accepts 2 parameters?
I found somewhere that MAX should do it, but it doesn't work... it only works on selecting the MAX of a column.
If there is no such function, does anybody have an idea what a stored procedure to do this might look like? (I have no stored procedure experience, so I have no clue what DB2 would be capable of).

Why does MAX not work for you?
select max(1,2,8,3,1,7) from sysibm.sysdummy1
gives me
1
---------------
8
1 record(s) selected.

As Dave points out, MAX should work as it's overloaded as both a scalar and a column function (the scalar takes 2 or more arguments). This is the case in DB2 for LUW, DB2 for z/OS and DB2 for i5/OS. What exact version and platform of DB2 are you using, and what is the exact statement you are using? One of the requirements of the scalar version of MAX is that all the arguments are "compatible" - I suspect there may be a subtle type difference in one or more of the arguments you're passing to the function.

On Linux V9.1, the "select max (1,2,3) ..." gives -
SQL0440N No authorized routine named "MAX" of type "FUNCTION" having
compatible arguments was found. SQLSTATE=42884
It is a scalar function requiring either a single value or a single column name. On z/os, it behaves differently.
However, It does work as expected on Linux 9.5.

Two options:
What about sorting the column in descending and grabbing the top 1 row?
According to my "SQL Pocket Guide", MAX(x) returns the greatest value in a set.
UPDATE: Apparently #1 won't work if you are looking at columns.

It sounds crazy, but no such function exists in DB2, at least not in version 9.1. If you want to select the greater of two columns, it would be best to use a case expression.
You can also define your own max function. For example:
create function importgenius.max2(x double, y double)
returns double
language sql
contains sql
deterministic
no external action
begin atomic
if y is null or x >= y then return x;
else return y;
end if;
end
Defining the inputs and outputs as doubles lets you take advantage of type promotion, so this function will also work for integers. The "deterministic" and "no external action" statements help the database engine optimize use of the function.
If you want another max function to work for character inputs, you'll have to give it another name.

Please check with following query:
select * from table1 a,
(select appno as sub_appno,max(sno) as sub_maxsno from table1 group by appno) as tab2
where a.appno =tab2.sub_appno and a.sno=tab2.sub_maxsno

Related

MIN function in ORACLE and SQL Server working differently

I am trying to convert the Oracle script to SQL Server script. But it seems my MIN() function is not working as expected as it is being executed in Oracle.
For SQL Server :
SELECT MIN(v)
FROM (VALUES ('20013E17587A1_2'), ('20013E17587_2')) AS value(v);
Result: 20013E17587_2
However,
For ORACLE :
SELECT MIN(t.value)
FROM tab t;
Result: 20013E17587A1_2
I am getting this as a result. Can somebody explain why is this difference and what can be done to have same result?
Different sort rules. You're asking the database whether it considers _ to come before or after A. By default, Oracle uses a binary sort (and the code point 65 belonging to A is less than code point 95 belonging to _) while SQL Server uses the default collation of the database, which will be a linguistic ordering where _ is considered to precede any letter. If you want SQL Server to exhibit identical behavior, use something like
SELECT MIN(v COLLATE Latin1_General_BIN2)
FROM (VALUES ('20013E17587A1_2'), ('20013E17587_2')) AS value(v);
Actual correct placement of the COLLATE depends on your "real" query, which I presume this isn't -- you may want to change the collation of the column itself in the CREATE TABLE, for example.
Because Oracle looks for the ASCII value for each character during the comparison of each respective character ordered within the string while performing alphanumeric sorting. This is called binary sort which's default for Oracle DB.
ASCII('A') equals 65, and ASCII('_') equals 95. If the string was 20013E17587.2 instead of 20013E17587_2, then you'd get 20013E17587.2 as result, since ASCII('.') equals 46 which is less than 65.

SQL Select to keep out fields that are NULL

I am trying to connect a Filemaker DB to Firebird SQL DB in both ways import to FM and export back to Firebird DB.
So far it works using the MBS Plug-in but FM 13 Pro canot handle NULL.
That means that for example Timestamp fields that are empty (NULL) produce a "0" value.
Thats means in Time something like 01.01.1889 00:00:00.
So my idea was to simply ignore fields containing NULL.
But here my poor knowlege stops.
First I thought I can do this with WHERE, but this is ignoring whole records sets:
SELECT * FROM TABLE WHERE FIELD IS NOT NULL
Also I tried to filter it later on like this:
If (IsEmpty (MBS("SQL.GetFieldAsDateTime"; $command; "FIELD") ) = 0 ; MBS("SQL.GetFieldAsDateTime"; $command; "FIELD"))
With no result either.
This is a direct answer to halfbit's suggestion, which is correct but not for this SQL dialect. In a query to provide a replacement value when a field is NULL you need to use COALESCE(x,y). Where if X is null, Y will be used, and if Y is null then the field is NULL. Thats why it is common for me to use it like COALESCE(table.field,'') such that a constant is always outputted if table.field happens to be NULL.
select COALESCE(null,'Hello') as stackoverflow from rdb$database
You can use COALESCE() for more than two arguments, I just used two for conciseness.
I dont know the special SQL dialect, but
SELECT field1, field2, value(field, 0), ...FROM TABLE
should help you:
value gives the first argument, ie, your field if it is NOT NULL or the second argument if it is.

how to return the value of a scalar function in db2

I have a db2 function returning an integer. As per my limited knowledge the only way to see this function working is using to return column in a query like the example below.
Is there a way to display a return value of a function given a parameter withoyt building up a more complex query?
Example
I have a function
myfoo(index integer) returns integer ...
And I am using it in a more complex quewry like
select myIndex, myfoo(myIndex), myValue from MyTable...
If I try to get the following
select from myfoo(3)
it will not work.
Is there any db2 function to print out the return value of that function without error?
SELECT myfoo(3) FROM SYSIBM.SYSDUMMY1
SYSIBM.SYSDUMMY1 is a special "dummy" table that contains a single row, the equivalent of Oracle's DUAL.
If you have the compatibility vector, you can even use Oracle's Dual table. http://pic.dhe.ibm.com/infocenter/db2luw/v10r5/topic/com.ibm.db2.luw.apdv.porting.doc/doc/r0052874.html
Also, you can use the 'values' sentence. For example,
values myfoo(myIndex)

Simple Math max function in MySQL

How to find the maximum of two explicit values in MySQL? Something like MAXIMUM(1, #foo).
There are group functions like MAX, MIN, AVG, etc that take column name as an argument and work with result sets. Is it possible to convert two explicit values to a result set and use those functions? Some other ways?
P.S.: I need a max function for one of my stored procedures.
How to find the maximum of two explicit values in MySQL? Something like MAXIMUM(1, #foo).
Use the GREATEST function:
GREATEST(1, #foo)
...will return whichever value is larger - if 1 is larger than the value in #foo, you'll get 1. Otherwise, you'll get whatever value is in #foo. Also, it's not an aggregate function.
The alternative would be to use a CASE statement:
CASE WHEN 1 > #foo THEN 1 ELSE #foo END
...because CASE is ANSI standard - that will work on Oracle, MySQL, SQL Server, Postgres...
You can use IF(1 > #foo,1,#foo)

Scalar Max in Sql Server

How to implement the scalar MAX in Sql server (like Math.Max). (In essense I want to implement something like Max(expression, 0), to make negative values replaced by 0.)
I've seen in other threads solutions with
creating a scalar function (how's that with performance?)
case when expression > 0 THEN expression ELSE 0) (then 'expression' is evaluated twice?)
complicated uses of
Max(aggregate).
What's the best?
Why does Sql Server not have something like this built in? Any complications I don't see?
In all other major systems this function is called GREATEST.
SQL Server seriously lacks it.
You can make a bunch of case statements, or use something like this:
SELECT (
SELECT MAX(expression)
FROM (
SELECT expression
UNION ALL
SELECT 0
) q
) AS greatest
FROM table_that_has_a_field_named_expression
The latter one is a trifle less performant than CASE statements.
you want to create a user-defined scalar function named MAX in sql server to take two parameters as input, an expression and a min value, and return the expression if it exceeds the min value, otherwise return the min value?
I wouldn't worry about the performance of scalar functions, let the server do that.
I'd also use IF instead of CASE to test for > min value.
SQL server doesn't have a built in function for you because they didn't think it would be widely enough used, I guess.
The query optimizer should prevent the expression from being calculated multiple times.
For readability / maintainability, consider using a CTE to calculate the expression before the CASE statement.