it-swarm-eu.dev

Použití stejného případu, když podmínky pro více sloupců dotazu

Existuje „lepší“ způsob, jak přepsat klauzuli SELECT, kde několik sloupců používá stejné CASE WHEN podmínky, aby byly podmínky zkontrolovány pouze jednou?

Viz příklad níže.

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

V psuedo-kódu bez sql by kód mohl vypadat takto:

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

Poznámka:

  • Jsem si vědom zjevných normalizačních problémů, které z dotazu plynou. Chtěl jsem jen ukázat problém.
13
Steven

I v Oracle (a ve skutečnosti v SQL standardu) je CASE výraz, který vrací jedinou hodnotu. Používá se ne pro řízení toku, jako je tomu v některých jiných jazycích. Proto jej nelze použít k podmíněnému rozhodování mezi více sloupci nebo jinými operacemi.

Řekl bych, že si prohlédnete delší verzi kódu (která již funguje) a nemějte s tím starosti ve svých formálních dotazech.

Můžete také zvážit normalizovanější design. Například proč neukládat informace o auditu do samostatné tabulky, s typem jako součástí klíče? Díky tomu je váš kód mnohem snazší udržovat, zejména když se přidává více typů ...

7
Aaron Bertrand

Pokud jsou všechny tyto sloupce ze stejné tabulky, můžete použít něco podobného:

    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' ;
7
ypercubeᵀᴹ