Order by and Different Types in a CASE

删除回忆录丶 提交于 2019-12-23 09:29:55

问题


I have a requirement to order a result set by a column, based on an Integer input into a parameter.

Problem is, I need to use a CASE for the OrderBy, and it seems the code accepts the first 'TYPE' in the case column... any other types fail.

My code is like this:

    WITH error_table AS  
 (  
  SELECT Row_Number() OVER   
   (ORDER BY  
        CASE @orderBy
            WHEN 1 THEN received_date  -- Last Rx'd message  
            WHEN 2 THEN message_id -- Message Id  
            WHEN 3 THEN zibmat.short_name -- Message action type  
            WHEN 4 THEN error_action.short_name -- Status type  
            WHEN 5 THEN ime.[allocated_date] -- Allocated Date  
            ELSE received_date
    END) AS RowNumber   

   ,ime.[ijis_message_error_id]  
      ,ime.[message_id]  
      ,ime.[message_version] 

So, when OrderBy is 1, it works. It sorts by rx_date... but when I sent it a 2, it fails with a data time conversion error.

It looks like all the types must be the same...

Sending a 5 works fine, as that's a date time too.

Is there a way I can fix this?


回答1:


A CASE statement must resolve to only one data type. This is regardless of the fact that you know that @orderby will choose only one branch and it will be a particular data type.

You could use something like this, which would be clunky but will work.

ORDER BY
CASE @orderBy WHEN 1 THEN received_date -- Last Rx'd message
WHEN 2 THEN 0
WHEN 3 THEN 0
WHEN 4 THEN 0
WHEN 5 THEN ime.[allocated_date] -- Allocated Date
ELSE received_date END,
CASE @orderBy WHEN 1 THEN 0
WHEN 2 THEN message_id -- Message Id
WHEN 3 THEN 0
WHEN 4 THEN 0
WHEN 5 THEN 0
ELSE 0 END,
CASE @orderBy WHEN 1 THEN ''
WHEN 2 THEN ''
WHEN 3 THEN zibmat.short_name -- Message action type
WHEN 4 THEN error_action.short_name -- Status type
WHEN 5 THEN ''
ELSE '' END



回答2:


This also appears to work.

ORDER BY  
        CASE @orderBy
            WHEN 1 THEN CAST(received_date AS SQL_VARIANT)  -- Last Rx'd message  
            WHEN 2 THEN message_id -- Message Id  
            WHEN 3 THEN zibmat.short_name -- Message action type  
            WHEN 4 THEN error_action.short_name -- Status type  
            WHEN 5 THEN ime.[allocated_date] -- Allocated Date  
            ELSE received_date
    END

Test case (int, string, date)

DECLARE @P INT = Datepart(SECOND, Getdate())%3;

SELECT 'Sorting By ' + CASE @P
            WHEN 1 THEN 'modify_date'
            WHEN 2 THEN 'object_id'
            ELSE 'name'
          END  

SELECT object_id,
       name,
       modify_date
FROM   sys.objects
ORDER  BY CASE @P
            WHEN 1 THEN CAST(modify_date AS SQL_VARIANT)
            WHEN 2 THEN object_id
            ELSE name
          END  



回答3:


I think the following one would be more cleaner option (similar to RichardTheKiwi's approach)

WITH error_table AS  
(  
    SELECT ROW_NUMBER() OVER 
            (
            ORDER BY
                CASE WHEN @orderBy = 1 THEN received_date END,
                CASE WHEN @orderBy = 2 THEN message_id END ,
                CASE WHEN @orderBy = 3 THEN zibmat.short_name END,
                CASE WHEN @orderBy =4 THEN error_action.short_name END, 
                CASE WHEN @orderBy =5 THEN ime.[allocated_date] END 
            ) AS RowNumber

    ,ime.[ijis_message_error_id]  
    ,ime.[message_id] 
    --..other columns...
    -- FROM YOURTABLE
)


来源:https://stackoverflow.com/questions/5214613/order-by-and-different-types-in-a-case

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!