Question

From this table:

Select * into #tmp from (
select 'a' A, 'b' B, NULL C union all
select 'aa' A, 'ab' B, 1 C union all
select 'aaa' A, 'bbb' B, 2 C ) x

I'd like to get this result:

A   B   Val
a   b   1
aa  ab  1
aaa bbb 2

That is, take the non-null min value and replace the NULL.

I suppose I could join the table to a filtered version of itself where no nulls appear. But that seems overkill. I thought this might be able to be done in the MIN Aggregate clause itself.

Any ideas would be helpful, thanks!

Was it helpful?

Solution

declare @null int

select @null = MIN(c) from #tmp

select A, B, ISNULL(c,@null) as val1 from #tmp

or

select A, B, ISNULL(c,(select MIN(c) from #tmp)) as val1 from #tmp

OTHER TIPS

EDIT: I wrote "You want something like ISNULL(c, MIN(c)) but that's not possible."

But I'm wrong, it is possible. I was missing something in my syntax, so @kiki47's answer is exactly what you are asking for.


I wouldn't phrase it as "I suppose I could join the table to a filtered version of itself where no nulls appear," but more or less you can get the min and the use it.

In one go:

WITH cte AS (
  SELECT MIN(c) minVal FROM #tmp WHERE c IS NOT NULL
)
SELECT a, b, ISNULL(c, cte.minVal) 
  FROM #tmp 
 CROSS JOIN cte

or maybe simpler (but may optimize to the same thing):

DECLARE @minVal INTEGER
SELECT @minVal = MIN(c) FROM #tmp WHERE c IS NOT NULL
SELECT a, b, ISNULL(c, @minVal) FROM #tmp 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top