【问题标题】:SQL Server - Setting Multiple Values in a Case Statement?SQL Server - 在案例语句中设置多个值?
【发布时间】:2026-02-02 02:35:02
【问题描述】:

我有一个 SQL Select 语句,我需要根据条件返回某些值。我每次都需要返回多个值,但我对Case语句的理解是,每个case只能返回一个值。

我目前正在通过使用 UNION 语句来解决这个问题,但这看起来有点麻烦 - 有没有更好的方法来做到这一点?基本上,我有一堆提示,每个提示都有“是”、“否”或“将来”的响应(实际上我有更多的响应,但我将仅使用 3 作为示例以保持简短!) - 我需要为每种响应类型生成一个列,其中 1 作为适当响应的值,而 0 表示所有其他响应。看SQL可能更清楚...

我的(简化的)查询如下所示:

SELECT branch,
       promptType,
       response,
       1 AS 'Yes',
       0 AS 'No',
       0 AS 'Not Discussed'
FROM prompts
WHERE response = 'Y'

UNION

SELECT branch,
       promptType,
       response,
       0 AS 'Yes',
       1 AS 'No',
       0 AS 'Not Discussed'
FROM prompts
WHERE response = 'N'

UNION

SELECT branch,
       promptType,
       response,
       0 AS 'Yes',
       0 AS 'No',
       1 AS 'Not Discussed'
FROM prompts
WHERE response = 'D'

【问题讨论】:

    标签: sql sql-server select case


    【解决方案1】:

    类似...

    SELECT branch,
           prompttype,
           CASE WHEN response = 'Y' THEN 'Yes'
                WHEN response = 'N' THEN 'No'
                WHEN response = 'D' THEN 'Not Discussed'
        FROM prompts;
    

    可能是你所追求的。

    在您发表评论后,也许...

    SELECT branch,
           prompttype,
           CASE WHEN response = 'Y' THEN 1 ELSE 0 AS Yes,
           CASE WHEN response = 'N' THEN 1 ELSE 0 AS No,
           CASE WHEN response = 'D' THEN 1 ELSE 0 AS Not_Discussed
        FROM prompts;
    

    可能会这样做。

    【讨论】:

    • 我每次都需要返回所有 3 个响应,仅返回值为 0 或 1。因此提示值(“是”、“否”、“未讨论”)实际上是列标题和每条记录在每个字段中都有一个 0 或 1。我从原始帖子中的 UNION 语句得到的输出实际上是正确的输出,我只是认为可能有更好的方法来生成它。
    • 啊。我懂了。那我再考虑一下。
    • 谢谢 :-) 本质上,我需要能够从 Case 语句中为每一行设置“是”、“否”和“未讨论”列的值,但我我不确定这是可能的。可以用 If 语句代替吗?如果没有,联盟就只能这么做了,感觉就像是重复了很多次。
    • 不,我不相信这是可能的。大概除了数字的选择之外,您还有其他想法;否则我看不出三列是一起设置还是分开设置的。
    • 我总是在这样的CASE 语句中添加ELSE 'UNKNOWN: '+COALESCE('"'+response+'"','null')。如果有人添加了新值但不更新此代码,这将有所帮助。然而,最好的办法是添加一个新表:Responses,带有一个 char(1) PK:Response,带有一个 FK 到 prompts.response 和一个 varchar(100)ResponseDescription,以及三位 /微小的 int 列:YesNoNot_discussed。插入您的 Y - N - D 行,然后加入这个新表并返回 YesNoNot_discussed 列。这样,如果添加了任何新响应,您的代码将处理它们。
    【解决方案2】:

    您是否考虑过为响应创建解码表并加入其中?

    例如,这将创建一个用于解码响应的表:

    CREATE TABLE decoder (response CHAR(1), [Yes] BIT, [No] BIT, [Not Discussed] BIT)
    INSERT INTO decoder VALUES ('Y', 1, 0, 0)
    INSERT INTO decoder VALUES ('N', 0, 1, 0)
    INSERT INTO decoder VALUES ('D', 0, 0, 1)
    

    ...然后您可以加入它以获得与您的 UNION 相似(相同?)的结果:

    SELECT
        prompts.branch,
        prompts.prompttype,
        prompts.response,
        decoder.yes,
        decoder.no,
        decoder.[Not Discussed]
    FROM 
        prompts INNER JOIN decoder ON prompts.response = decoder.response
    

    可能是一种值得考虑的方法;这是一个比你的 union 更具关系性的解决方案,并且可能更容易维护。

    【讨论】:

    • 有意思,我试试看!没想到,谢谢:-)
    • 被接受为最佳答案,结果查询比我原来的更易于维护。
    【解决方案3】:

    我认为您需要添加分组。我通过季度预测来做到这一点。如果每个响应都有一个唯一的 ID,它将是这样的(否则它将为整个分支/提示类型/响应选择最大值):

    SELECT uniqueID,
       branch,
       prompttype,
       response,
       MAX(CASE WHEN response = 'Y' THEN 1 ELSE 0 END) AS Yes,
       MAX(CASE WHEN response = 'N' THEN 1 ELSE 0 END) AS [No],
       MAX(CASE WHEN response = 'D' THEN 1 ELSE 0 END) AS  Not_Discussed
    FROM prompts
    
    GROUP BY uniqueID,
        branch,
        prompttype,
        response;
    

    【讨论】:

      【解决方案4】:
      SELECT branch,
             prompttype,
          response,
             CASE WHEN response = 'Y' THEN 1 ELSE 0 END AS Yes,
             CASE WHEN response = 'N' THEN 1 ELSE 0 END AS [No],
             CASE WHEN response = 'D' THEN 1 ELSE 0 END AS  Not_Discussed
          FROM prompts;
      

      【讨论】:

      • 这与 Brian 的回答相同 - 它不会产生所需的输出。
      【解决方案5】:

      如果您提议的CASE 语句在单个列中返回多个值,那么数据类型是什么:数组、列表、表格、XML 文档、业务对象等?对于真正的关系数据库管理系统 (TRDBMS),答案将是关系变量。但我们在这里讨论的是 SQL Server。

      我认为您正在寻找的答案是 SQL Server 的数据类型是标量,而不是多值。

      【讨论】:

      • 我不想在单个列中有多个值,我想返回多个列,但在 case 语句中设置它们的值,以便输出与我的原始查询产生的相同.