tags:

views:

6259

answers:

6

I want to add two numbers together but when one of those numbers is null then the result is null. Is there a way around this. I could simply do it in the code but I would rather have it done in the query. This is a oracle database.

The table structure

hours_t
type     craft    regular       overtime
 A         1        5              0
 A         1        3              1
 B         2        9            <null>
 B         1        4              4

The query

select type, craft, sum(regular + overtime) as total_hours
from hours_t
group by type, craft
order by type, craft

The unwanted results

type   craft   total_hours
  A      1          9
  B      1          8
  B      2        <null>

The wanted results

type    craft   total_hours
  A       1          9
  B       1          8
  B       2          9
+9  A: 
select type, craft, sum(nvl(regular,0) + nvl(overtime,0)) as total_hours
from hours_t
group by type, craft
order by type, craft
Tony Andrews
A: 
select type, craft, sum(NVL(regular, 0) + NVL(overtime, 0)) as total_hours
from hours_t
group by type, craft
order by type, craft
Quassnoi
+7  A: 

NVL(value, default) is the function you are looking for.

select type, craft, sum(NVL(regular, 0) + NVL(overtime, 0) ) as total_hours
from hours_t
group by type, craft
order by type, craft

Oracle have 5 NULL-related functions:

  1. NVL
  2. NVL2
  3. COALESCE
  4. NULLIF
  5. LNNVL

NVL:

NVL(expr1, expr2)

NVL lets you replace null (returned as a blank) with a string in the results of a query. If expr1 is null, then NVL returns expr2. If expr1 is not null, then NVL returns expr1.

NVL2 :

NVL2(expr1, expr2, expr3)

NVL2 lets you determine the value returned by a query based on whether a specified expression is null or not null. If expr1 is not null, then NVL2 returns expr2. If expr1 is null, then NVL2 returns expr3.

COALESCE

COALESCE(expr1, expr2, ...)

COALESCE returns the first non-null expr in the expression list. At least one expr must not be the literal NULL. If all occurrences of expr evaluate to null, then the function returns null.

NULLIF

NULLIF(expr1, expr2)

NULLIF compares expr1 and expr2. If they are equal, then the function returns null. If they are not equal, then the function returns expr1. You cannot specify the literal NULL for expr1.

LNNVL

LNNVL(condition)

LNNVL provides a concise way to evaluate a condition when one or both operands of the condition may be null.

More info on Oracle SQL Functions

zendar
great info thanks
Berek Bryan
You could have thrown in CASE and DECODE for completeness ;)
David Aldridge
+1  A: 

You need to use the NVL function, e.g.

SUM(NVL(regular,0) + NVL(overtime,0))

Turnkey
+4  A: 

The other answers regarding the use of nvl() are correct however none seem to address a more salient point:

Should you even have NULLs in this column?

Do they have a meaning other than 0?

This seems like a case where you should have a NOT NULL DEFAULT 0 on th ecolumn

cletus
The first goal of SO should be to answer the OP. Programmers have a need. That need is to have a question answered. Do you even know if BerekBryan has the ability to change the column? Has he even met the person who can change it? I know we all want to show how smart we are but let's stick to the OP
@Mark Brady, I don't really agree. It's not "how smart we are", but rather suggesting alternative ways of approaching the problem. The OP may or may not have the ability to change the column, but the comment is useful (if not for him then possibly for others who read this thread).
Hosam Aly
@cletus, I think this is more appropriate as a comment on the question rather than a separate answer.
Hosam Aly
@Mark: you can answer the OP and advise better approached at the same time. It makes for a better answer.
cletus
Consider this: overtime report comes late. 0 means - no overtime for period, NULL means - we did not get information for given period. Without NULL you need extra field for getting list of "types" for whom we didn't get data.
zendar
cletus makes a good point but I do not have control over the database.
Berek Bryan
@Berek: that's bad design and overuse of a single column especially when you need to go wrap the field in NVL() to turn it into 0!
cletus
+3  A: 

The top-rated answer with NVL is totally valid. If you have any interest in making your SQL code more portable, you might want to use CASE, which is supported with the same syntax in both Oracle and SQL Server:

select 
  type,craft,
  SUM(
    case when regular is null
         then 0
         else regular
    end
    +
    case when overtime is null
         then 0
         else overtime
    end
  ) as total_hours
from 
  hours_t
group by
  type
 ,craft
order by
  type
 ,craft
JosephStyons
nice alternative, thanks
Berek Bryan