Aggregate functions with NULL not behaving as expected - sql

With SQLite, I'm attempting a simple MAX():
SELECT MAX(100, NULL);
This returns null. Shouldn't it be 100 instead?
According to the documentation:
Aggregate max() returns NULL if and only if there are no non-NULL values in the group.
100 is a non-null value, so I would not expect to get null returned from MAX() in this case. Am I misunderstanding the documentation? And, how can I use MAX(), by either ignoring null values in the set, or by treating them as zero 0?

That's not the aggregate version.
From the right documentation:
The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL.
and
Note that max() is a simple function when it has 2 or more arguments but operates as an aggregate function if given only a single argument.

Related

SQLite SUM function and strings

I have the following problem.
Let's say that I have a table foo:
CREATE TABLE foo
(
mycolumn INTEGER
);
INSERT INTO foo VALUES (1);
INSERT INTO foo VALUES (2);
INSERT INTO foo VALUES ("");
then, the result of SELECT SUM(mycolumn) FROM foo; is:
SUM(mycolumn)
-------------
3.0
If I updated the empty string to NULL the result would be 3. It is understandable as aggregate functions disregard NULL values. However, I do not understand the floating point result given above (3.0).
I cannot find any information about TEXT to REAL conversion on SQLite Datatypes page. Therefore, I have the following question:
Is there an automatic conversion from TEXT to REAL storage class when an aggregate function is used?
PS. I am using version 3.34.1 of SQLite.
From the SQLite documentation on aggregates:
The result of sum() is an integer value if all non-NULL inputs are integers. If any input to sum() is neither an integer or a NULL then sum() returns a floating point value which might be an approximation to the true sum.
Check the sqlite documentation
sum(X) total(X)
The sum() and total() aggregate functions return sum of all non-NULL
values in the group. If there are no non-NULL input rows then sum()
returns NULL but total() returns 0.0. NULL is not normally a helpful
result for the sum of no rows but the SQL standard requires it and
most other SQL database engines implement sum() that way so SQLite
does it in the same way in order to be compatible. The non-standard
total() function is provided as a convenient way to work around this
design problem in the SQL language.
The result of total() is always a floating point value. The result of
sum() is an integer value if all non-NULL inputs are integers. If any
input to sum() is neither an integer or a NULL then sum() returns a
floating point value which might be an approximation to the true sum.
Sum() will throw an "integer overflow" exception if all inputs are
integers or NULL and an integer overflow occurs at any point during
the computation. Total() never throws an integer overflow.

Is it possible to use a COALESCE function inside a SUM function?

I'm trying to use COALESCE function at postgres in a query like this:
SELECT
id_school,
SUM(COALESCE((student->'name'->>'age'), '0')::numeric)
FROM
teachers
GROUP BY 1;
The problem is at line:
SUM(COALESCE((student->'name'->>'age'), '0')::numeric)
I tried to use COALESCE because I'm receiving some empty strings and the ERROR: invalid input syntax for type numeric: ""
Shouldn't COALESCE solve this casting error? Can't I use COALESCE in a SUM function?
You don't actually need the coalesce() function inside the sum, because sum will ignore NULL values anyway.
You error isn't caused by a NULL value, but by an empty string.
So you need to convert the empty string to a NULL value. This can be done using nullif() in Postgres
SELECT id_school,
SUM(nullif(student->'name'->>'age'), '')::numeric)
FROM teachers
GROUP BY 1;
If you could also have strings with blanks in it the JSON value, you might want to consider nullif(trim(student->'name'->>'age'), '')
COALESCE returns first non-null argument. Empty string is non-null. You are trying to cast '' to numeric value.
You can use NULLIF to get null instead of empty string in COALESCE.
SQL Coalesce with empty string

Division by NULL in IBM DB2

In Oracle, any number divided by NULL returns NULL. I was wondering what is the case for DB2 Databases?
The whole point of it is to check whether the following expression behaves in the same way for Oracle and DB2:
SELECT a / NULLIF(b, 0) FROM some_table;
Say b=0, we would get a division by null.
The NULLIF function returns the null value if the two arguments are equal; otherwise, it returns the value of the first argument.
-NULLIF(expression,expression)-------------------------------
The result of using NULLIF(e1,e2) is the same as using the CASE expression:
CASE WHEN e1=e2 THEN NULL ELSE e1 END
Copy
When e1=e2 evaluates to unknown because one or both arguments is null, CASE expressions consider the evaluation not true. In this case, NULLIF returns the value
of the first argument.
IBM DB2 docs
So for DB2 and oracle it works same way
Db2 returns null when one of the operators in a math expression is null. For example
values (3 / cast(null as integer)) will return null.
On the other hand, the definition of NULLID is equal to that in Oracle. If both arguments are equal, it will return null.

SQL: AVG with NULL Values

As far as I understood, the AVG() function ignores NULL Values.
So AVG(4,4,4,4,4,NULL) --> 4
In my case I don't want this to happen.
I need a solution like that: AVG(4,4,4,4,4,NULL) --> 3,33
without replacing the NULL values directly in the table itself.
Is there any way to do this?
Use coalesce() to return the real value of zero for null columns:
select avg(coalesce(some_column, 0))
from ...
You are correct about the behavior of AVG - use COALESCE to convert the NULLs to 0 in the aggregate.
See this answer in "Why SUM(null) is not 0 in Oracle?"
If you are looking for a rationale for this behaviour, then it is to be found in the ANSI SQL standards which dictate that aggregate operators ignore NULL values.
The relevant code is then, simply:
Avg(Coalesce(col,0))
You can use coalesce or nvl also.
Since coalesce examples are already given above, here is an example of nvl
Avg(Nvl(Column_Name),0)
Coalesce, Nvl, Nvl2 functions are handy in such cases of handling null values.
You should look up some examples and documentation on these.
NVL, NVL2, or COALESCE could be used to solve this issue.
like this
select avg(4,4,4,4, nvl(null, 0 )) from dual;
Another possibility is to calculate average using aggregate functions SUM with COUNT
SELECT SUM(column_with_value) / COUNT(primary_column) FROM ...

Select with NVL2 Not working Oracle

I am selecting values from the database using Functions. I have three different functions in which if the first does not return anything I check for the second and third functions for values using NVL2. The problem is when I execute independent functions they return values but not in the NVL2 function My query is:
select NVL2(CRBP.FPDATE(LAM.ACID),
CRBP.FPDATE1(LAM.ACID),
CRBP.ODSANCDATE(GAM.ACID)) from
tbaadm.lam, TBAADM.GAM
where gam.acid = lam.acid
and gam.acid = 'VM12990'
This does not return any value.
But when I execute :
select CRBP.FPDATE (LAM.ACID) from tbaadm.lam where lam.acid = 'VM12990';
This Already returns a value. Shouldn't this be the value returned by my first query considering that it is the first in the check. What is the Problem with My first Query??
If CRBP.FPDATE returns a value the query should return the value returned by the function CRBP.FPDATE1 and if CRBP.FPDATE returns NULL then the query should return CRBP.ODSANCDATE's vlaue.
Does CRBP.FPDATE1 return anything?
NVL2(a,b,c) is a "if a is null then a else b" type function. so the value of a is never returned.
it sounds like you want COALESCE which will return the first not null value from the set of parameters