Использование одного и того же случая при выполнении условий для нескольких столбцов запросов

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

В не SQL-псевдо-коде код может выглядеть следующим образом:

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

Замечания:

  • Я знаю об очевидных проблемах нормализации, подразумеваемых запросом. Я только хотел продемонстрировать проблему.
Стивен
источник
И все эти колонны authTime, authUser, cmplTimeнаходятся в одной и той же таблицы?
ypercubeᵀᴹ
Похожий вопрос: stackoverflow.com/q/13713316/4632019
Евгений Коньков

Ответы:

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' ;
ypercubeᵀᴹ
источник
2
Я думал об этом, но это так же скучно. Я не думаю, что есть хороший способ сделать это.
Philᵀᴹ
Он отвечает на вопрос +1, но, как уже указывали другие, то, с чего вы начали, лучше. Вы также можете объединить значения, соответствующие каждому testStatus, а затем разделить их, но это будет еще хуже.
Ли Риффель