如何在SQL Server中使用CASE WHEN选择多列?

40

我在这个网站上进行了广泛的搜索,但找不到解决方案。

以下是我的查询示例:

SELECT 
   ActivityID,

   Hours = (CASE 
                WHEN ActivityTypeID <> 2 THEN
                     FieldName = (Some Aggregate Sub Query),
                     FieldName2 = (Some other aggregate sub query)
                WHEN ActivityTypeID = 2 THEN
                     FieldName = (Some Aggregate Sub Query with diff result),
                     FieldName2 = (Some Other Aggregate Sub Query with diff result)
           END)

显然我省略了查询的很多部分,我只是想看看是否可能。

我知道我可能可以两次使用 "CASE" 但是想问一下...


相关问题,但不是重复的,链接为https://dev59.com/SWYr5IYBdhLWcg3wYpUg - Nameless One
4个回答

37

问题在于你试图使用CASE语句的方式不正确。你只能在查询中使用它来切换一个字段的值。如果我理解你的意图,你可能需要这个:

SELECT 
   ActivityID,
   FieldName = CASE 
                  WHEN ActivityTypeID <> 2 THEN
                      (Some Aggregate Sub Query)
                  ELSE
                     (Some Aggregate Sub Query with diff result)
               END,
   FieldName2 = CASE
                  WHEN ActivityTypeID <> 2 THEN
                      (Some Aggregate Sub Query)
                  ELSE
                     (Some Aggregate Sub Query with diff result)
               END

17

不,CASE是一个函数,只能返回单个值。我想你需要复制你的CASE逻辑。

另一个选项是用IF包装整个查询,并有两个单独的查询来返回结果。如果没有看到查询的其余部分,很难说这是否适用于您。


3

"Case"只能返回单个值,但您可以使用复合类型:

create type foo as (a int, b text);
select (case 1 when 1 then (1,'qq')::foo else (2,'ww')::foo end).*;

3
我认为在Postgres中可能是可以的,但在SQL Server(该问题所标记的)中不行。 - dsz
请注意,这明显是关于PostgreSQL的内容,绝对不是M$ SQL Server:https://popsql.com/learn-sql/postgresql/how-to-do-type-casting-in-postgresql/。但无论如何,评论很好。 - scavenger

1

实际上你可以做到。

尽管如此,有人应该注意到重复CASE语句并不像看起来的那么糟糕。SQL Server的查询优化器足够聪明,不会执行两次CASE,因此您不会因此而受到任何性能影响。

此外,如果适合您,有人可能会使用以下逻辑来避免重复使用CASE。

INSERT INTO dbo.T1
(
    Col1,
    Col2,
    Col3
)
SELECT
    1,
    SUBSTRING(MyCase.MergedColumns, 0, CHARINDEX('%', MyCase.MergedColumns)),
    SUBSTRING(MyCase.MergedColumns, CHARINDEX('%', MyCase.MergedColumns) + 1, LEN(MyCase.MergedColumns) - CHARINDEX('%', MyCase.MergedColumns))
FROM
    dbo.T1 t
LEFT OUTER JOIN
(
    SELECT CASE WHEN 1 = 1 THEN '2%3' END MergedColumns
) AS MyCase ON 1 = 1

这将为表格T1中的每个记录插入值(1、2、3)。使用分隔符“%”来拆分合并的列。您可以根据需要编写自己的拆分函数(例如,处理空记录或使用复杂的varchar字段分隔符等)。但主要逻辑是应该连接CASE语句,并使用拆分逻辑从连接的结果集中进行选择。

谢谢您注意到这不是性能问题 :) 我只会在我的CASE语句中使用它两次,哈哈 - vivasuzi
好主意,但它引入了一些问题:可能会出现转换问题(例如,浮点数->字符串->浮点数),您引入了一个不应出现在数据中的字符(而且数据随时间而变化),代码变得相当难以阅读,我猜性能也不是很好,因为需要进行大量的字符串处理(想象一下数百万行)。在这种情况下,我实际上更喜欢重复自己,而不是严格遵循DRY原则。 - mzuther

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接