SQL query to add values of two columns containing null values? - sql

Given table:
ID ONE TWO
X1 15 15
X2 10 -
X3 - 20
This query:
SELECT (ONE + TWO) FROM (TABLE)
Just returns the sum of X1's values but not the others since at least one column has a null value. How can I still add them even if there is a null? i.e. consider the null as a 0 maybe?

SELECT (COALESCE(ONE, 0) + COALESCE(TWO, 0)) FROM (TABLE)
COALESCE will return the first non-null value found in the parameters from left to right. So, when the first field is null, it will take the 0.
That way, X2 will result in 10 + 0 = 10

there is already a good answer, but I think it is worth mention to the antonpug (in case he doesn't know) that the reason why this is happening is that NULL is not a value that can be compared or summed.
NULL isn't 0 or '' (empty string), so every operation involving NULL will result NULL (10 + NULL = NULL), even (NULL=NULL) will evaluate to FALSE

Related

How to set flag based on values in previous columns in same table ? (Oracle)

I'm creating a new table and carrying over several columns from a previous table. One of the new fields that I need to create is a flag that will have values 0 or 1 and value needs to be determined based on 6 previous fields in the table.
The 6 previous columns have preexisting values of 0 or 1 stored for each one. This new field needs to check whether any of the 6 columns have 1 and if so set the flag to 0. If there is 0 in all 6 fields then set itself to 1.
Hopefully this makes sense. How can I get this done in oracle? I assume a case statement and some sort of forloop?
You can use greatest() function: GREATEST
create table t_new
as
select
case when greatest(c1,c2,c3,c4,c5,c6)=1 -- at least one of them contains 1
then 0
else 1
end c_new
from t_old;
Or even shorter:
create table t_new
as
select
1-greatest(c1,c2,c3,c4,c5,c6) as c_new
from t_old;
In case of greatest = 1, (1-1)=0, otherwise (1-0)=1
You can use a virtual column with a case expression; something like:
flag number generated always as (
case when val_1 + val_2 + val_3 + val_4 + val_5 + val_6 = 0 then 1 else 0 end
) virtual
db<>fiddle
or the same thing with greatest() as #Sayan suggested.
Using a virtual column means the flag will be right for newly-inserted rows, and if any of the other values are updated; you won't have to recalculate or update the flag column manually.
I've assumed the other six columns can't be null and are constrained to only be 0 or 1, as the question suggests. If they can be null you can add nvl() or coalesce() to each term in the calculation.

How to divide columns with zeros and nulls

just a simple question but somehow I can't find an answer here.
I have two columns (A and B). Both contains numbers with zeros and null. I would like to get a division one by the other to get information about the ratio between each single row but I am getting ORA-01476.
I know the divisior is equal to zero but I would like to get in this row a number and not an error for whole query
A B
1 5
2 Null
3 0
NULL 3
0 4
4
I am using sql developer.
If you divide a number by zero you get an error, because the answer to such division is undefined. SQL, however, has a value for undefined: NULL. So make the result NULLinstead:
select a, b, case when b = 0 then null else a / b end as ratio
from mytable;
or
select a, b, a / case when b = 0 then null else b end as ratio
from mytable;
This is standard SQL and works in Oracle as well as in about every other RDBMS. Oracle also provides the function NULLIF as a shorter way to write the expression in the second query.
You can use nullif to return null instead of raising an error:
select A / nullif(B, 0) as division
from YourTable
If your numbers are stored as varchar, cast them to numbers before using them:
select to_number(A) / nullif(to_number(B), 0) as division
from YourTable

SQL: sum 3 columns when one column has a null value without replacing null with 0?

Given table:
ID ANOTHERID ONE TWO THREE
X1 B1 15 15 -
X1 B2 10 - -
X2 B1 - 20 -
This query:
SELECT SUM (ONE + TWO + THREE) FROM (TABLE)
GROUP BY ID, ANOTHERID
I also tried
select sum(coalesce( ONE + TWO + THREE, ONE + TWO, ONE + THREE, ONE +
THREE))
at least one column has a null value. How can I still add them even if there is a null? As null and 0 have different meanings here (null means not started, 0 means not worked), I dont want to replace null with 0. Thanks
One method is:
SELECT SUM(COALESCE(ONE, 0) + COALESCE(TWO, 0) + COALESCE(THREE, 0))
FROM (TABLE)
GROUP BY ID, ANOTHERID;
Or, if you have at least one non-NULL value in each column:
SELECT SUM(ONE) + SUM(TWO) + SUM(THREE)
The time reporting table(s) should not allow null values, and the employee table should have a hire date field which can be used as criteria in your reporting queries. This will enable you to accurately report what management expects.
This solution worked for me
select
case when coalesce(sum(ONE), sum(TWO), sum(THREE)) is null then null else
sum(nvl(ONE,0) + nvl(TWO,0) + nvl(THREE,0)) end as
TOTALSUM
GROUP BY ID, ANOTHERID;
You might need to add another column in your table that describes the status of the employee (new, old) then make a condition like this:
if emp_status = 'new' then
--some code
working_hours := null;
else
--some code
working_hours : 0;
end if;

unusual sql server query result

Let's say I have a table called nameAge:
ID Name Age
1 X 12
2 Y 12
3 null null
4 Z 12
and when I run a query like:
select * from nameAge where Age <> 12
it returns me an empty result set while I have row with id 3 where age is different than null?
Using Sql Server 2008 R2.
Any ideas?
Edit: Possibility to be duplicate with suggested answer may be at one point but does not cover at all and it shows how to use null values when compared with null but what I wanted to ask was about the result set which includes null values
This is the intended behavior. You cannot compare NULL values using = or <>. You have to use IS NULL or IS NOT NULL.
If you want NULL values only use IS NULL:
select * from nameAge where age IS NULL
If you want NULL values with age <> 12 values, use:
select * from nameAge where age <> 12 OR age IS NULL
The expression
WHERE NULL <> 12
does not return TRUE or FALSE, but actually returns UNKNOWN. This means that the third record in your table will not be returned by your query.
As #ughai mentioned, you should use IS NULL instead to query that record:
SELECT * FROM nameAge WHERE age IS NULL
Have a look at the Microsoft SQL Server documentation for more information.
When you are dealing with NULLs you should be always careful because of 3 valued logic used in Sql Server(when a predicate can be evaluated to TRUE, FALSE or UNKNOWN). Now here is a classic select statement where many newcomers make a mistake, suggesting that the statement would return all rows where Age <> 12 including NULLs.
But if you know the easy fact that comparing NULL to any value, even to NULL itself will evaluate to UNKNOWN it is getting more clear what is going on. WHERE clause will return ONLY those rows where predicate is evaluated to TRUE. Rows where predicate evaluates to FALSE or UNKNOWN will be filtered out from resultset.
Now let's see what is going on behind the scene. You have 4 rows:
ID Name Age
1 X 12
2 Y 12
3 null null
4 Z 12
and the predicate is:
where Age <> 12
When you evaluate this predicate for each row you get:
ID Name Age Evaluation result
1 X 12 FALSE --(because 12 <> 12 is FALSE)
2 Y 12 FALSE --(because 12 <> 12 is FALSE)
3 null null UNKNOWN --(because NULL <> 12 is UNKNOWN)
4 Z 12 FALSE --(because 12 <> 12 is FALSE)
Now remember that WHERE clause will return only rows where predicate evaluates to TRUE and it is clear that you will not get any result because no row evaluates to TRUE.

Why does AVG(x) give a different answer than AVR((isnull(x,0))?

X is column with a mixture of numerical and null values.
I don't understand why treating null values as 0 changes the result of the AVG value.
Shouldn't it be like this,
(2 + null + 2) / 3 = 2 -- with null value
(2 + 0 + 2) / 3 = 2 -- no null value
If you have null value, it is not being taken into account, hence number of elements (your n) is not increased, whereas 0 is treated as a valid value.
For example if you have: 1,1,6,7,null,3,2 it will be total 20 divided by 6 (i.e. 3.33). However if you replace null with 0 it becomes 20 /7 (i.e. 2.86).
SQLFiddle demonstrating this behavior on MySQL server.
REFERENCE: Have a look in the documentation right below the table:
This section describes group (aggregate) functions that operate on sets of values. Unless otherwise stated, group functions ignore NULL values.