Reputation: 839
I have a query where based on a column value, my sort will be dynamic. So, it is something like this:
ROW_NUMBER() OVER (PARTITION BY last_action
ORDER BY CASE
WHEN last_action = 'Insert' THEN company_name
ELSE percent_change
END DESC
Issue here is that they are different data types, so it throws an error. If I convert the "percent_change" to character, then it does not sort numerically. And, to complicate things, they want the "percent_change" in DESC and the "company_name" in ASC.
So, I was thinking if there is a way to convert the actual "company_name" into some numerical value, and subtract it from 0, and then I can so the numerical sort in DESC order.
Any ideas would be helpful.......
Upvotes: 2
Views: 263
Reputation: 2460
Have you looked at using the DECODE function?
Decode is kind of like a simplified CASE statement. You can use it in the order by clause (or anywhere you can use an expression)
DECODE(expr, key1, value1, key2, value2, default)
For example:
ORDER BY DECODE(tbl.companyName, 'name1', 1, 'name2', 2, 'name3', 3, 9999)
The last value is the default if the first expression doesn't match.
In your example, I think you can combine CASE and DECODE to yield the final expression for the order by clause.
Anther trick for sorting numbers as characters is to pad the string with leading zeros. You can use LPAD or concatenation and substr (RIGHT)
LPAD(expr, 9, '0'); SUBRSTR('000000000' || expr, -9);
I use something like the above to fix SSNs that have had leading 0 dropped (for example when they come through Excel)
Upvotes: 0
Reputation: 23578
Sounds like you're after something like this, then:
ROW_NUMBER() OVER (PARTITION BY last_action
ORDER BY CASE
WHEN last_action = 'Insert' THEN company_name
END,
CASE
WHEN last_action = 'Insert' THEN NULL
ELSE percent_change
END DESC NULLS LAST)
This works by splitting the ordering out into two expressions, but because they're conditional on the column in the partition by
clause, only one of them is going to impact the ordering at any one time.
Upvotes: 6
Reputation: 13509
What if you take your case outside of window function -
CASE WHEN last_action = 'Insert' THEN
ROW_NUMBER() OVER(PARTITION BY last_action ORDER BY company_name)
ELSE ROW_NUMBER() OVER(PARTITION BY last_action ORDER BY percent_change DESC)
END
Upvotes: 4