Utilisation des mêmes conditions CASE WHEN pour plusieurs colonnes de requête


12

Existe-t-il une "meilleure" façon de réécrire une SELECTclause où plusieurs colonnes utilisent les mêmes CASE WHENconditions afin que les conditions ne soient vérifiées qu'une seule fois?

Voir l'exemple ci-dessous.

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 code pseudo non SQL, le code pourrait ressembler à:

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

Remarque:

  • Je suis conscient des problèmes de normalisation évidents impliqués par la requête. Je voulais seulement démontrer le problème.

Et toutes ces colonnes authTime, authUser, cmplTimesont dans la même table?
ypercubeᵀᴹ

Réponses:


7

Même dans Oracle (et en fait dans la norme SQL), CASEest une expression qui renvoie une seule valeur. Il n'est pas utilisé pour contrôler le flux comme il l'est dans certaines autres langues. Par conséquent, il ne peut pas être utilisé pour décider conditionnellement entre plusieurs colonnes ou d'autres opérations.

Je dirais de mettre la version plus longue du code (qui fonctionne déjà) dans une vue, et ne vous inquiétez pas à ce sujet dans vos requêtes formelles.

Vous pouvez également envisager une conception plus normalisée. Par exemple, pourquoi ne pas stocker les détails de l'audit dans une table séparée, avec le type dans la clé? Cela rend votre code beaucoup plus facile à maintenir, d'autant plus que davantage de types sont ajoutés ...


Even in Oracle... mais dans Postgres, cela est possible en développant le type composite.
Eugen Konkov

7

Si toutes ces colonnes proviennent de la même table, vous pouvez utiliser quelque chose comme ceci:

    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
J'ai réfléchi à la publication de cela, mais c'est tout aussi long. Je ne pense pas qu'il y ait une bonne façon de procéder.
Philᵀᴹ

Il répond à la question +1, mais comme d'autres l'ont indiqué, ce que vous avez commencé est meilleur. Vous pouvez également concaténer les valeurs correspondant à chaque testStatus, puis les séparer, mais ce serait encore pire.
Leigh Riffel
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.