Uso del mismo caso cuando las condiciones para varias columnas de consulta


12

¿Existe una forma "mejor" de reescribir una SELECTcláusula en la que varias columnas usan las mismas CASE WHENcondiciones para que las condiciones se verifiquen solo una vez?

Vea el ejemplo a continuación.

SELECT
    CASE testStatus 
        WHEN 'A' THEN 'Authorized'
        WHEN 'C' THEN 'Completed'
        WHEN 'P' THEN 'In Progress'
        WHEN 'X' THEN 'Cancelled'
    END AS Status,

    CASE testStatus 
        WHEN 'A' THEN authTime
        WHEN 'C' THEN cmplTime
        WHEN 'P' THEN strtTime
        WHEN 'X' THEN cancTime
    END AS lastEventTime,

    CASE testStatus 
        WHEN 'A' THEN authBy
        WHEN 'C' THEN cmplBy
        WHEN 'P' THEN strtBy
        WHEN 'X' THEN cancBy
    END AS lastEventUser
FROM test

En el código psuedo no sql, el código podría verse así:

CASE testStatus
    WHEN 'A'
        StatusCol        = 'Authorized'
        lastEventTimeCol = authTime 
        lastEventUserCol = authUser
    WHEN 'C'
        StatusCol        = 'Completed'
        lastEventTimeCol = cmplTime
        lastEventUserCol = cmplUser
    ...
END

Nota:

  • Soy consciente de los problemas obvios de normalización que implica la consulta. Solo quería demostrar el problema.

Y todas estas columnas authTime, authUser, cmplTimeestán en la misma mesa?
ypercubeᵀᴹ

Respuestas:


7

Incluso en Oracle (y de hecho en el estándar SQL), CASEes una expresión que devuelve un solo valor. Se no se utiliza para el control de flujo como lo es en algunos otros idiomas. Por lo tanto, no se puede usar para decidir condicionalmente entre múltiples columnas u otras operaciones.

Yo diría que coloque la versión más larga del código (que ya funciona) en una vista, y no se preocupe por eso en sus consultas formales.

También podría considerar un diseño más normalizado. Por ejemplo, ¿por qué no almacenar los detalles de auditoría en una tabla separada, con el tipo como parte de la clave? Esto hace que su código sea mucho más fácil de mantener, especialmente a medida que se agregan más tipos ...


Even in Oracle... pero en Postgres eso es posible expandiendo el tipo compuesto.
Eugen Konkov

7

Si todas estas columnas son de la misma tabla, puede usar algo como esto:

    SELECT  
        'Authorized' AS StatusCol,
        authTime     AS lastEventTimeCol, 
        authUser     AS lastEventUserCol 
    FROM test
    WHERE testStatus = 'A'

  UNION ALL

    SELECT  
        'Completed', 
        cmplTime,
        cmplUser    
    FROM test
    WHERE testStatus = 'C'

  UNION ALL

    SELECT  
        'In Progress', 
        strtTime,
        strtUser    
    FROM test
    WHERE testStatus = 'P'

  UNION ALL

    SELECT  
        'Cancelled', 
        cancTime,
        cancUser    
    FROM test
    WHERE testStatus = 'X' ;

2
Pensé en publicar eso, pero es igual de largo. No creo que haya una buena manera de hacerlo.
Philᵀᴹ

Responde la pregunta +1, pero como otros han indicado, lo que comenzó es mejor. También podría concatenar los valores que corresponden a cada testStatus y luego separarlos, pero eso sería aún peor.
Leigh Riffel
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.