2

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.......

1
  • Please show sample data Commented Jan 24, 2022 at 16:07

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

This appears to work, as well as the item from Ankit. Many thanks.
How to make it work when you want to use many columns, and the types don't match for each case?
@user2340939 - the types don't match here already. There is one order-by term for each column, each with a case expression which means it only takes effect if a condition is met. So you can just add extra terms, one for each extra column, with suitable conditions.
4

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

2 Comments

This appears to work, as well as the item from Boneist. Many thanks as well.
How to make it work when you want to use many columns, and the types don't match for each case?
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.