Використання того ж випадку, коли умови для кількох стовпців запитів


12

Чи існує "кращий" спосіб переписати SELECTпункт, коли кілька стовпців використовують однакові CASE WHENумови, щоб умови перевірялися лише один раз?

Дивіться приклад нижче.

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

У psuedo-коді, який не є sql, код може виглядати так:

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

Примітка:

  • Мені відомо про очевидні проблеми нормалізації, які має на увазі запит. Я хотів лише продемонструвати проблему.

І всі ці колони authTime, authUser, cmplTimeзнаходяться в одній і тій же таблиці?
ypercubeᵀᴹ

Відповіді:


7

Навіть в Oracle (а насправді в стандарті SQL) CASE- це вираз, який повертає єдине значення. Він не використовується для контролю потоку, як це є в деяких інших мовах. Тому його не можна використовувати для прийняття умовного рішення серед кількох стовпців або інших операцій.

Я б сказав, що перегляньте довшу версію коду (яка вже працює), і не турбуйтеся про це у формальних запитах.

Ви також можете розглянути більш нормалізовану конструкцію. Наприклад, чому б не зберігати дані аудиту в окремій таблиці з типом як частиною ключа? Це робить ваш код набагато простішим в обслуговуванні, тим більше, що додано більше типів ...


Even in Oracle... але в Postgres, що можливо шляхом розширення складеного типу.
Євген Конков

7

Якщо всі ці стовпці з однієї таблиці, ви можете використовувати щось подібне:

    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
Я розмірковував над публікацією, але це так само довго. Я не думаю, що це є приємний спосіб зробити це.
Philᵀᴹ

Він відповідає на питання +1, але, як зазначали інші, краще, з чого ви почали. Ви також можете об'єднати значення, що відповідають кожному testStatus, а потім розділити їх на частини, але це було б ще гірше.
Лі Ріффер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.