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:
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ů ...
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' ;