Reputation: 1747
So I have this basic setup:
Declare @temp Table(t1 varchar(1)
,t2 int)
insert into @temp (t1,t2)
Values
('a','1')
,('a','2')
,('a','3')
,('a','4')
,('a',null)
select t1,t2,ROW_NUMBER() OVER ( PARTITION BY T1 ORDER BY t2) 'rnk'
from @temp
The problem is, the value that is Null get ranked the highest. What I am trying to do is set the first non zero/null value to the highest rank(lowest number) current output is:
t1 t2 rnk
a NULL 1
a 0 2
a 1 3
a 2 4
a 3 5
I want
t1 t2 rnk
a NULL 4/5 --either or
a 0 4/5
a 1 1
a 2 2
a 3 3
I know i can do this with subquerys but the problem is to get t2, is a 200 character case statement that i really don't want to copy and paste all over, once to calculate, then one to order by and such. I am seeing a Query to get the values, inside a query to get the rank,inside a query to only pull those ranked 1, which is 3 deep and i don't know like that. note i know it say oracle and i am sure at least one person will mark me down since this is in SQL server, BUT, the actual code is in oracle, i am just much better in SQL server and its easy to translate unless Oracle has some magic function that makes this easier.
Upvotes: 1
Views: 784
Reputation: 1270513
You can use two keys for the order by
. The following is compatible with both SQL Server and Oracle:
select t1, t2,
ROW_NUMBER() OVER (PARTITION BY T1
ORDER BY (CASE WHEN t2 IS NOT NULL OR T2 <> 0 THEN 0 ELSE 1 END),
t2
) as rnk
from @temp;
Oracle supports NULLS LAST
, which makes it easier: ORDER BY t2 NULLS LAST
.
Upvotes: 5
Reputation: 6713
Another option would be to use the ISNULL
function to set it to the max value of the type on null values. So if t2
is an integer it would be:
select t1,t2,ROW_NUMBER() OVER ( PARTITION BY T1 ORDER BY ISNULL(t2,2147483647)) 'rnk'
from @temp
This would prevent you from having to use t2
(your big case statement) in your expression more than once.
I believe Oracle uses NVL
instead of ISNULL
.
Upvotes: 0