首页 > 解决方案 > 对新创建的列使用 CASE WHEN

问题描述

我在 SQL Server 中有一个表,我按 ID 对它进行了分组,并创建了 2 个包含其他数据计数的新列。我希望能够同时创建另一列,如果两列中的计数都大于数字,则显示 1,否则将显示 2。但是当我尝试它时,它说无效的列名,我猜是我的计数列不在原始表中?

我的数据类似于:

    ID    Data1    Data2
-------------------------
0    1       1       5
1    1       2       5
2    1       5       8
3    1       7       9
4    2       8       5
5    2       7       3
6    2       9       2
7    3       3       1
8    3       3       6
9    3       2       7
10   3       6       3
11   3       8       0

期望的输出(如果 >= 4,则代码​​为 1,否则为 2):

   ID  CountData1  CountData2  Code
------------------------------------
0   1           4           4     1
1   2           3           3     2
2   3           5           5     1

当前查询:

SELECT 
    ID,
    COUNT(Data1) AS CountData1,
    COUNT(Data2) AS CountData2,
    (CASE WHEN (CountData1 >= 4 and CountData2 >= 4) THEN 1 ELSE 2 END) AS Code
FROM 
    Table
GROUP BY 
    ID

标签: sqlsql-servertsqlgroup-bycase

解决方案


SQL 语句的解析方式,您不能引用您刚刚在同一范围内创建的表达式。

您可以再次重复表达式:

SELECT 
    ID,
    COUNT(Data1) AS CountData1,
    COUNT(Data2) AS CountData2,
    (CASE WHEN (COUNT(Data1) >= 4 and COUNT(Data2) >= 4) THEN 1 ELSE 2 END) 
    AS Code
FROM 
    dbo.Table
GROUP BY 
    ID;

或者使用 CTE 或派生表:

-- CTE

;WITH cte AS 
(
  SELECT ID, 
      COUNT(Data1) AS CountData1,
      COUNT(Data2) AS CountData2
    FROM dbo.Table 
    GROUP BY ID
)
SELECT ID, CountData1, CountData2,
  CASE WHEN CountData1 >= 4 AND CountData2 >- 4 
    THEN 1 ELSE 2 END AS Code
FROM cte;

-- Derived Table

SELECT ID, CountData1, CountData2,
  CASE WHEN CountData1 >= 4 AND CountData2 >- 4 
    THEN 1 ELSE 2 END AS Code
FROM     
(
  SELECT ID, 
      COUNT(Data1) AS CountData1,
      COUNT(Data2) AS CountData2
    FROM dbo.Table 
    GROUP BY ID
) AS DerivedTable;

尽管有些人认为第一个更糟,因为您引用了COUNT()额外的时间,但这些都执行相同的操作。SQL Server 非常擅长不重复不必要的工作,事实上,上面的所有三个查询都产生完全相同的执行计划,具有完全相同的成本、相同的读取次数、相同的输出和完全相同的数量表达式的计算。CPU 和持续时间会略有不同,因为计算机。

这三个计划都是一样的

如果您遇到 CTE 产生比重复表达式更好的计划的情况(请注意,在某些情况下,两种变体可能会产生多个计数表达式),请将其发布在某处。


推荐阅读