10

I have the following SP that I am using to paginate a list of news articles. As you may be able to guess, @count is the number of rows to return, @start is the index to select rows from (sorted by inner query), @orderby indicates the column to sort by, and @orderdir indicates whether to sort one direction or the other. My original query was here, before I added the @orderdir parameter.

ALTER PROCEDURE [mytable].[news_editor_paginate]
    @count int,
    @start int,
    @orderby int,
    @orderdir int
AS 
BEGIN
    SET NOCOUNT ON; 
    SELECT TOP (@count) * FROM 
    (  
        SELECT ne.*,n.publishstate, 
            (CASE WHEN @orderdir = 1 THEN
                ROW_NUMBER() OVER (
                    ORDER BY                    
                        CASE WHEN @orderby = 0 THEN ne.[time] END DESC,
                        CASE WHEN @orderby = 1 THEN ne.lastedit END DESC,    
                        CASE WHEN @orderby = 2 THEN ne.title END ASC
                    )
            WHEN @orderdir = 2 THEN
                ROW_NUMBER() OVER (
                    ORDER BY                    
                        CASE WHEN @orderby = 0 THEN ne.[time] END ASC,    
                        CASE WHEN @orderby = 1 THEN ne.lastedit END ASC,
                        CASE WHEN @orderby = 2 THEN ne.title END DESC
                    )
                END
            ) AS num
            FROM news_edits AS ne
            LEFT OUTER JOIN news AS n
            ON n.editid = ne.id 
        ) 
     AS a
    WHERE num > @start
END

Now nothing actually goes wrong, but the @orderby parameter doesn't work. If provide 1 as the @orderdir parameter, it will give me the exact same results as if I provide 2 as that parameter.

Community
  • 1
  • 1
James Hay
  • 7,115
  • 6
  • 33
  • 57
  • Does this answer your question? [SQL stored procedure passing parameter into "order by"](https://stackoverflow.com/questions/12407247/sql-stored-procedure-passing-parameter-into-order-by) – Raúl Diego Mar 16 '21 at 16:19
  • @RaúlDiego Maybe, but this was like 9 years ago and the accepted answer worked perfectly at the time, so I'm going to leave it. – James Hay Mar 17 '21 at 01:20

2 Answers2

22

Row number isn't evaluated on every row, however case statements are so you're stuck with the rownum no matter what the case.

Try this instead:

            ROW_NUMBER() OVER (
                ORDER BY                    
                    CASE WHEN @orderby = 0 AND @orderdir = 1 THEN ne.[time] END DESC,    
                    CASE WHEN @orderby = 0 AND @orderdir = 2 THEN ne.[time] END ASC,    
                    CASE WHEN @orderby = 1 AND @orderdir = 1 THEN ne.lastedit END DESC,
                    CASE WHEN @orderby = 1 AND @orderdir = 2 THEN ne.lastedit END ASC,
                    CASE WHEN @orderby = 2 AND @orderdir = 1 THEN ne.title END ASC
                    CASE WHEN @orderby = 2 AND @orderdir = 2 THEN ne.title END DESC
                )
Gats
  • 3,452
  • 19
  • 20
  • 1
    Yup that worked exactly how I wanted, it seems so obvious now that you've written it down. Thanks, have to wait to mark this as the answer. – James Hay Apr 04 '12 at 21:58
  • No sweat. Scratched my head over this stuff a few times before when row_number came out. – Gats Apr 07 '12 at 02:46
4

This works fine for me - (where,order by,direction,offset fetch)

       -- parameters

        @orderColumn  int ,
        @orderDir  varchar(20),
        @start  int ,
        @limit  int


        select * from items
        WHERE        (items.status = 1) 
        order by 

        CASE WHEN @orderColumn = 0 AND @orderdir = 'desc' THEN items.[category] END DESC,    
        CASE WHEN @orderColumn = 0 AND @orderdir = 'asc' THEN items.[category] END ASC,    
        CASE WHEN @orderColumn = 1 AND @orderdir = 'desc' THEN items.[category] END DESC,
        CASE WHEN @orderColumn = 1 AND @orderdir = 'asc' THEN items.[category] END ASC,
        CASE WHEN @orderColumn = 2 AND @orderdir = 'desc' THEN items.[category] END DESC,
        CASE WHEN @orderColumn = 2 AND @orderdir = 'asc' THEN items.[category] END ASC

        OFFSET @start ROWS FETCH NEXT @limit ROWS ONLY 
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87