One cross-database option uses coalesce() and case expressions. This assumes that not all of the values will be null on the same record.
select
(
coalesce(val1, 0)
+ coalesce(val2, 0)
+ coalesce(val3, 0)
+ coalesce(val4, 0)
+ coalesce(val5, 0)
+ coalesce(val6, 0)
+ coalesce(val7, 0)
+ coalesce(val8, 0)
) / (
case when val1 is null then 0 else 1 end
+ case when val2 is null then 0 else 1 end
+ case when val3 is null then 0 else 1 end
+ case when val4 is null then 0 else 1 end
+ case when val5 is null then 0 else 1 end
+ case when val6 is null then 0 else 1 end
+ case when val7 is null then 0 else 1 end
+ case when val8 is null then 0 else 1 end
) res
from mytable;
Another standard solution is to use union all and aggregation. Assuming that the primary key of your table is id, you would go:
select id, avg(val) res
from (
select id, val1 val from mytable
union all select id, val2 val from mytable
union all select id, val3 val from mytable
union all select id, val4 val from mytable
union all select id, val5 val from mytable
union all select id, val6 val from mytable
union all select id, val7 val from mytable
union all select id, val8 val from mytable
) t
group by id
The second solution actually highlights the fact that you should fix your data model to store the values in rows, not in columns.