2011-03-07 11 views
5

Tengo un requerimiento para ordenar un conjunto de resultados por una columna, basado en una entrada de Entero en un parámetro.Orden por y Diferentes tipos en un CASO

El problema es que necesito usar una CASE para el OrderBy, y parece que el código acepta el primer 'TYPE' en la columna de casos ... cualquier otro tipo falla.

Mi código es así:

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] 

lo tanto, cuando OrdenarPor es 1, funciona. Se ordena por rx_date ... pero cuando lo envié a 2, falla con un error de conversión de tiempo de datos.

Parece que todos los tipos deben ser los mismos ...

Envío de un 5 funciona bien, ya que es una fecha y hora también.

¿Hay alguna manera de solucionarlo?

+0

"¿Hay una manera Puedo arreglar esto? "Sí, hacer que todos sean del mismo tipo de datos –

+0

@Richard aka cyberkiwi: Estoy al tanto de eso . No especifiqué nada específicamente: presumiblemente el relleno apropiado estaría involucrado. Anteriormente resolví esto de la manera en que respondió a continuación ... –

Respuesta

7

Una instrucción CASE debe resolverse en un solo tipo de datos. Esto es independientemente del hecho de que usted sabe que @orderby elegirá solo una rama y será un tipo de datos particular.

Puede usar algo como esto, que sería torpe pero funcionará.

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 
+0

+1: La otra alternativa es SQL dinámico para una cláusula dinámica ORDER BY. –

+0

+1. Así es como lo he implementado previamente. –

+0

Esto funciona realmente bien, gracias. Aunque entiendo, ¿qué está haciendo? Si tenemos 1 seleccionado (tipo de fecha y hora), está ordenando de forma absoluta antes de la fecha recibida, 0, 0, 0, ¿verdad? Donde si pasamos en un 3, ordenaría por 0, 0, zibmat.short_name, 0? – Craig

4

Esto también parece funcionar.

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 

caso de prueba (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 
1

Creo que la opción más limpia siguiente sería más (similar al enfoque de RichardTheKiwi)

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 
) 
+0

Formatee su código – NoNaMe

+0

Este debe ser el aceptado ... –

Cuestiones relacionadas