SQL: AVG with NULL Values - sql

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 ...

Related

Avoid division by zero in PostgreSQL

I'd like to perform division in a SELECT clause. When I join some tables and use aggregate function I often have either null or zero values as the dividers. As for now I only come up with this method of avoiding the division by zero and null values.
(CASE(COALESCE(COUNT(column_name),1)) WHEN 0 THEN 1
ELSE (COALESCE(COUNT(column_name),1)) END)
I wonder if there is a better way of doing this?
You can use NULLIF function e.g.
something/NULLIF(column_name,0)
If the value of column_name is 0 - result of entire expression will be NULL
Since count() never returns NULL (unlike other aggregate functions), you only have to catch the 0 case (which is the only problematic case anyway). So, your query simplified:
CASE count(column_name)
WHEN 0 THEN 1
ELSE count(column_name)
END
Or simpler, yet, with NULLIF(), like Yuriy provided.
Quoting the manual about aggregate functions:
It should be noted that except for count, these functions return a
null value when no rows are selected.
I realize this is an old question, but another solution would be to make use of the greatest function:
greatest( count(column_name), 1 ) -- NULL and 0 are valid argument values
Note:
My preference would be to either return a NULL, as in Erwin and Yuriy's answer, or to solve this logically by detecting the value is 0 before the division operation, and returning 0. Otherwise, the data may be misrepresented by using 1.
Another solution avoiding division by zero, replacing to 1
select column + (column = 0)::integer;
If you want the divider to be 1 when the count is zero:
count(column_name) + 1 * (count(column_name) = 0)::integer
The cast from true to integer is 1.

What applications are there for NULLIF()?

I just had a trivial but genuine use for NULLIF(), for the first time in my career in SQL. Is it a widely used tool I've just ignored, or a nearly-forgotten quirk of SQL? It's present in all major database implementations.
If anyone needs a refresher, NULLIF(A, B) returns the first value, unless it's equal to the second in which case it returns NULL. It is equivalent to this CASE statement:
CASE WHEN A <> B OR B IS NULL THEN A END
or, in C-style syntax:
A == B || A == null ? null : A
So far the only non-trivial example I've found is to exclude a specific value from an aggregate function:
SELECT COUNT(NULLIF(Comment, 'Downvoted'))
This has the limitation of only allowing one to skip a single value; a CASE, while more verbose, would let you use an expression.
For the record, the use I found was to suppress the value of a "most recent change" column if it was equal to the first change:
SELECT Record, FirstChange, NULLIF(LatestChange, FirstChange) AS LatestChange
This was useful only in that it reduced visual clutter for human consumers.
I rather think that
NULLIF(A, B)
is syntactic sugar for
CASE WHEN A = B THEN NULL ELSE A END
But you are correct: it is mere syntactic sugar to aid the human reader.
I often use it where I need to avoid the Division by Zero exception:
SELECT
COALESCE(Expression1 / NULLIF(Expression2, 0), 0) AS Result
FROM …
Three years later, I found a material use for NULLIF: using NULLIF(Field, '') translates empty strings into NULL, for equivalence with Oracle's peculiar idea about what "NULL" represents.
NULLIF is handy when you're working with legacy data that contains a mixture of null values and empty strings.
Example:
SELECT(COALESCE(NULLIF(firstColumn, ''), secondColumn) FROM table WHERE this = that
SUM and COUNT have the behavior of turning nulls into zeros. I could see NULLIF being handy when you want to undo that behavior. If fact this came up in a recent answer I provided. If I had remembered NULLIF I probably would have written the following
SELECT student,
NULLIF(coursecount,0) as courseCount
FROM (SELECT cs.student,
COUNT(os.course) coursecount
FROM #CURRENTSCHOOL cs
LEFT JOIN #OTHERSCHOOLS os
ON cs.student = os.student
AND cs.school <> os.school
GROUP BY cs.student) t

What does this SQL Query mean?

I have the following SQL query:
select AuditStatusId
from dbo.ABC_AuditStatus
where coalesce(AuditFrequency, 0) <> 0
I'm struggling a bit to understand it. It looks pretty simple, and I know what the coalesce operator does (more or less), but dont' seem to get the MEANING.
Without knowing anymore information except the query above, what do you think it means?
select AuditStatusId
from dbo.ABC_AuditStatus
where AuditFrequency <> 0 and AuditFrequency is not null
Note that the use of Coalesce means that it will not be possible to use an index properly to satisfy this query.
COALESCE is the ANSI standard function to deal with NULL values, by returning the first non-NULL value based on the comma delimited list. This:
WHERE COALESCE(AuditFrequency, 0) != 0
..means that if the AuditFrequency column is NULL, convert the value to be zero instead. Otherwise, the AuditFrequency value is returned.
Since the comparison is to not return rows where the AuditFrequency column value is zero, rows where AuditFrequency is NULL will also be ignored by the query.
It looks like it's designed to detect a null AuditFrequency as zero and thus hide those rows.
From what I can see, it checks for fields that aren't 0 or null.
I think it is more accurately described by this:
select AuditStatusId
from dbo.ABC_AuditStatus
where (AuditFrequency IS NOT NULL AND AuditFrequency != 0) OR 0 != 0
I'll admit the last part will never do anything and maybe i'm just being pedantic but to me this more accurately describes your query.
The idea is that it is desireable to express a single search condition using a single expression but it's merely style, a question of taste:
One expression:
WHERE age = COALESCE(#parameter_value, age);
Two expressions:
WHERE (
age = #parameter_value
OR
#parameter_value IS NULL
);
Here's another example:
One expression:
WHERE age BETWEEN 18 AND 65;
Two expressions
WHERE (
age >= 18
AND
age <= 65
);
Personally, I have a strong personal perference for single expressions and find them easier to read... if I am familiar with the pattern used ;) Whether they perform differently is another matter...

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)

What is equivalent of the Nz Function in MS Access in MySQL? Is Nz a SQL standard?

What is MySQL equivalent of the Nz Function in Microsoft Access? Is Nz a SQL standard?
In Access, the Nz function lets you return a value when a variant is null. Source
The syntax for the Nz function is:
Nz ( variant, [ value_if_null ] )
The COALESCE() function does what you describe. It's standard SQL and it should be supported in all SQL databases.
The IFNULL() function is not standard SQL. Only some brands of databases support this function.
COALESCE does just what the OP is asking for, as does IFNULL:
SELECT Nz(MightBeNullVar, 0) FROM ... (MS Access version)
SELECT COALESCE(MightBeNullVar, 0) FROM ... (MySQL version)
SELECT IFNULL(MightBeNullVar, 0) FROM ... (MySQL version)
The difference is the COALESCE can search through multiple variables and return the first non-null one:
SELECT COALESCE(MightBeNullVar, MightAlsoBeNullVar, CouldBeNullVar, 0) FROM ... (MySQL version)
each of these will return a 0 (zero) if none of the values have a set value (are null).
The IFNULL is (pretty meaninglessly) faster. There's probably other better things to optimize in your query before bothering with IFNULL vs COALESCE issues. If you have multiple things to check, use COALESCE. If you only have a single value to check, use IFNULL.
You might want to look at IFNULL or COALESCE. If I recall correctly, IFNULL works for MySQL.
Have look to the null safe operator <=>
Maybe it could help :
http://dev.mysql.com/doc/refman/5.5/en/comparison-operators.html#operator_equal-to
Perhaps Knowing what MS Access NZ() Function actually does would be helpful (prior to answering with completely invalid suggestions). The NZ() Function test for Null and Replaces the Null with an empty string, a Zero or optionally a value that the user enters.
COALESCE doesn't even come close, in fact it returns a Null if no none Null values in a 'List???'
IFNULL() Function is what you're looking for.
http://dev.mysql.com/doc/refman/5.1/en/control-flow-functions.html