Acorian0
Acorian0

Reputation: 115

SQL Server conditional Order By with multiple columns

I have a table with thousands of executions that may have one of the following results in the state column:

OK
NOTOK
CANCELED
RUNNING

I need a query where i can sort the results so that the executions running appear on top, and the rest of the results are sorted by start date or ID, according to user preference.

example: Table records:

ID - STATE - START_DATE
1      OK      12:00
2    RUNNING   12:10
3     NOTOK    12:30
4    RUNNING   12:45
5      OK      13:00

Expect result when sorted by START_DATE:

ID - STATE - START_DATE
4   RUNNING    12:45
2   RUNNING    12:10
5     OK       13:00
3    NOTOK     12:30
1     OK       12:00

This is the query i already have (simplified):

SELECT TOP (@ITEMS_PAGE) ID, START_DATE, STATE
FROM 
    (SELECT ROW_NUMBER() OVER (ORDER BY
                                  CASE WHEN @ORDER = 'ID&ASC' THEN ID END ASC,
                                  CASE WHEN @ORDER = 'ID&DESC' THEN ID  END DESC,
                                  CASE WHEN @ORDER = 'START_DATE&ASC' THEN START_DATE END ASC,
                                  CASE WHEN @ORDER = 'START_DATE&DESC' THEN START_DATE END DESC,
                                  CASE WHEN @ORDER = 'STATE&ASC' THEN STATE END ASC,
                                  CASE WHEN @ORDER = 'STATE&DESC' THEN STATE END DESC,
                                  CASE WHEN @ORDER IS NULL THEN ID END DESC
                              ) AS ROWNUMBERS, * 
     FROM @TMPPAGING 
     WHERE (@RESULT is null or STATE = @RESULT)
) S
WHERE S.ROWNUMBERS > (@CURRENT_PAGE - 1) * @ITEMS_PAGE

@TMPPAGING contains the records.

Upvotes: 0

Views: 1216

Answers (1)

Brian Leach
Brian Leach

Reputation: 2101

You are making this much more complex than it needs to be. Here is your SQL for ordering by start_date:

with inputdata as ( select 1 as id, 'OK' as state, convert(datetime, '2018-01-10 12:00') as start_date
union all select 2 as id, 'RUNNING' as state, convert(datetime, '2018-01-10 12:10') as start_date
union all select 3 as id, 'NOTOK' as state, convert(datetime, '2018-01-10 12:30') as start_date
union all select 2 as id, 'RUNNING' as state, convert(datetime, '2018-01-10 12:45') as start_date
union all select 2 as id, 'OK' as state, convert(datetime, '2018-01-10 13:00') as start_date

) 
select * from inputdata order by case when state='RUNNING' then 1 else 2 end, start_date

This results in:

id  state   start_date
2   RUNNING 2018-01-10 12:10:00.000
2   RUNNING 2018-01-10 12:45:00.000
1   OK      2018-01-10 12:00:00.000
3   NOTOK   2018-01-10 12:30:00.000
2   OK      2018-01-10 13:00:00.000

Upvotes: 2

Related Questions