MySql - 如何将不同的别名分配给单个 select 列,由 case 语句确定

MySql - How to assign different aliases to a single select column, determined by a case statement

我有以下工作代码 (MySql 8.0):

    select user_id as "user",
        (case when userBad then CodeRed 
        else CodeBlue
        end)
    From colours

我想为 CodeRed 列分配别名 Red,为 CodeBlue 列分配别名 Blue。我知道我不能在案例陈述中提供别名。那么分配条件别名的正确语法是什么?我想也许我声明一个字符串变量来保存别名的值,然后将该变量附加到 case 语句:

declare alias varchar(4);
if userBad then set alias = "Red"
else set alias = "Blue";
select user_id as "user",
       (case when userBad then CodeRed 
       else CodeBlue
       end) as alias
From colours;

但正如您可能预料的那样,我最终得到了一个名为别名的列!那么有没有办法根据caseselect分配条件别名呢?谢谢

更新:Slava 提供了一个很好的解决方案,使用准备好的语句来连接别名变量。我的完整代码:我现在收到错误 1054:'field list' 中的未知列 userBad,但我相信 Slava 已让我走上正轨。

PROCEDURE `Test`(userBad bool)
BEGIN
    declare alias varchar(4);    

    drop temporary table if exists colours;
    create temporary table colours (user_id int, codeRed int, codeBlue int);
    

    if userBad then set alias = "Red";
    else set alias = "Blue";
    end if;
    
    SET @sql = CONCAT('select user_id as "user",
           (case when userBad = true then codeRed 
           else codeBlue
           end) as ', alias, ' from colours');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END

最终更新:我已经解决了“1054:'field list' 中的未知列 userBad”错误。我在下面发布了完整的工作解决方案。感谢 Slava 让我走上了使用预准备语句的正确轨道。

在存储过程中,您可以执行以下操作:

declare alias varchar(4);
if userBad then alias = "Red"
else alias = "Blue";

SET @sql = CONCAT('select user_id as ', alias, ' from colours');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

以上代码只是说明了动态查询的思路。您的查询可能有所不同。

下面是完整的存储过程代码。

PROCEDURE `Test`(userBad bool)
BEGIN
    declare alias varchar(4);    

    drop temporary table if exists colours;
    create temporary table colours (user_id int, codeRed int, codeBlue int);
    

    if userBad then 
        set alias = "Red";
    else 
        set alias = "Blue";
    end if;
    
    SET @sql = CONCAT(
        'select user_id as "user", code', alias, ' as ', alias, ' from colours'
    );

    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END;

另一个代码:

PROCEDURE `Test`(userBad bool)
    BEGIN
    
        drop temporary table if exists colours;
        create temporary table colours (user_id int, codeRed int, codeBlue int);
        
        if userBad then 
            SET @sql = 'select user_id as "user", codeRed as Red from colours';
        else 
            SET @sql = 'select user_id as "user", codeBlue as Blue from colours';
        end if;
    
        PREPARE stmt FROM @sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END;

我要感谢 Slava 使用准备好的语句让我走上正轨。这是一个不太有效的解决方案,其他解决方案也不完全是所需的结果。

准备好的语句是解决方案,但存在变量 userBad 被拒绝的问题。我意识到我们不能在准备好的语句中包含变量,但我们可以有一个占位符值,由 ? 表示,然后使用 userBad[=21= 执行语句].但是,这仍然会出错,因为执行准备语句的 USING 子句需要 user/session 变量,而不是局部变量。因此需要将局部变量userBad赋值给会话变量@uB。完整的工作解决方案如下:

PROCEDURE `Test`(userBad int)
BEGIN
    declare alias varchar(4);


    drop temporary table if exists colours;
    create temporary table colours (user_id int, codeRed int, codeBlue int);
    

    if userBad then set alias = "Red";
    else set alias = "Blue";
    end if;

    set @uB = userBad;
    SET @sql = CONCAT('select user_id as "user",
           (case when ? then codeRed 
           else codeBlue
           end) as ', alias, ' from colours');
    PREPARE stmt FROM @sql;
    EXECUTE stmt using @uB;
    DEALLOCATE PREPARE stmt
END

还有一点要补充,对于那些正在寻找这样的解决方案的人来说,如果您有多个会话变量,则需要按照语句中使用的顺序列出这些变量。