Question

I have a table with integer values. They could be negative, 0, positive and NULL. I need treat NULL as 0, calculate average for a given date and if average value is less than 0 then put 0 there.

My query is the following:

select
    Id, 
    ValueDate,
    case 
        when avg(isnull(Value, 0)) > 0 then avg(isnull(Value, 0))
        else 0
    end AvgValue
from SomeTable
where ValueDate = @givenDate
group by Id, ValueDate

How to avoid double aggregate function definition in case statement (aggregate statement could be much more complex)?

Was it helpful?

Solution 2

This is a solution without creating implementation of any not build-in functions. I know your example will be more complex but this is just an idea:

CREATE TABLE DataSource
(
    [ID] TINYINT
   ,[Value] INT
)

INSERT INTO DataSource ([ID], [Value])
VALUES (1, 2)
      ,(1, 0)
      ,(1, NULL)
      ,(1, 98)
      ,(1, NULL)
      ,(2, -4)
      ,(2, 0)
      ,(2, 0)
      ,(2, NULL)

SELECT [ID]
      ,MAX([Value])
FROM
(
  SELECT  [ID]
         ,AVG(COALESCE([Value],0))
  FROM DataSource
  GROUP BY [ID]
  UNION ALL
  SELECT DISTINCT [ID]
                 ,0
  FROM DataSource
) Data([ID],[Value])
GROUP BY [ID]

Here is the fiddle - http://sqlfiddle.com/#!6/3d223/14

OTHER TIPS

I think the greatest function could help you:

select
    Id, 
    ValueDate,
    greatest(avg(isnull(Value, 0)),0) AvgValue
from SomeTable
where ValueDate = @givenDate
group by Id, ValueDate
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top