对多个查询列使用相同的 CASE WHEN 条件

Ste*_*ven 14 oracle database-design best-practices oracle-10g

是否有“更好”的方法来重写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
Run Code Online (Sandbox Code Playgroud)

在非 sql 伪代码中,代码可能如下所示:

CASE testStatus
    WHEN 'A'
        StatusCol        = 'Authorized'
        lastEventTimeCol = authTime 
        lastEventUserCol = authUser
    WHEN 'C'
        StatusCol        = 'Completed'
        lastEventTimeCol = cmplTime
        lastEventUserCol = cmplUser
    ...
END
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我知道查询隐含的明显的规范化问题。我只是想证明这个问题。

ype*_*eᵀᴹ 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' ;
Run Code Online (Sandbox Code Playgroud)

  • 我考虑过发布那个,但它同样冗长。我不认为有什么好的方法可以做到。 (2认同)

Aar*_*and 7

即使在 Oracle(实际上在 SQL 标准中)中,CASE也是一个返回单个值的表达式。它不是用于流量控制就像它在某些其他语言。因此,它不能用于有条件地在多列或其他操作之间做出决定。

我会说将较长版本的代码(已经有效)放在视图中,不要在正式查询中担心它。

您还可以考虑更规范化的设计。例如,为什么不将审计详细信息存储在单独的表中,并将类型作为键的一部分?这使您的代码更易于维护,尤其是在添加更多类型时...