0

I have a few columns: Week1, Week2, Week3, Week4, Week5

i.e.

Week1 = 5
Week2 = 0
Week3 = 10
Week4 = 7
Week5 = 0

How do I calculate the average based on the fields that are not zero?

Incorrect: (5+0+10+7+0)/5 = 4.4

Correct: (5+0+10+7+0)/3 = 7.3

How to let create a custom column to let the SQL know that I only want to divide by 3 instead of 5?

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
user3486647
  • 191
  • 1
  • 4
  • 12

2 Answers2

3

If one or more columns are not zero, then they are averaged as you expected.
To obtain a null when all are zero:

select (week1+week2+week3+week4+week5)/
  nullif(
    case when week1=0 then 0 else 1 end +
    case when week2=0 then 0 else 1 end +
    case when week3=0 then 0 else 1 end +
    case when week4=0 then 0 else 1 end +
    case when week5=0 then 0 else 1 end,
  0)
from ....

To obtain a zero when all are zero:

select 
  coalesce((week1+week2+week3+week4+week5)/
  nullif(
    case when week1=0 then 0 else 1 end +
    case when week2=0 then 0 else 1 end +
    case when week3=0 then 0 else 1 end +
    case when week4=0 then 0 else 1 end +
    case when week5=0 then 0 else 1 end,
  0),0)
from ....

And if you want to be safe with null on columns:

select 
  coalesce((
    coalesce(week1,0) +
    coalesce(week2,0) +
    coalesce(week3,0) +
    coalesce(week4,0) +
    coalesce(week5,0) 
  )/
  nullif(
    case when coalesce(week1,0)=0 then 0 else 1 end +
    case when coalesce(week2,0)=0 then 0 else 1 end +
    case when coalesce(week3,0)=0 then 0 else 1 end +
    case when coalesce(week4,0)=0 then 0 else 1 end +
    case when coalesce(week5,0)=0 then 0 else 1 end,
  0),0)
from ....
David Andrei Ned
  • 799
  • 1
  • 11
  • 28
Saic Siquot
  • 6,513
  • 5
  • 34
  • 56
3

As a note, these types of problems (aggregation within a row) are often more easily expressed using apply:

select a.average
from table t cross apply
     (select avg(nullif(val, 0)) as average
      from (values (t.week1),
                   (t.week2),
                   (t.week3),
                   (t.week4),
                   (t.week5)
           ) v(val)
     ) a;
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786