【问题标题】:Using CASE WHEN with newly created columns对新创建的列使用 CASE WHEN
【发布时间】:2021-11-29 23:52:03
【问题描述】:

我在 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

【问题讨论】:

  • 您不能在同一个选择列表中使用它们。要么重复 count(),要么使用派生表(子查询)。

标签: sql sql-server tsql group-by case


【解决方案1】:

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 生成的计划比重复表达式更好 的情况(请注意,在某些情况下两种 变体可能会生成多个计数表达式) ,请在某处发布。

【讨论】:

  • 第二个选项在性能方面比第一个要好
  • @Yaseen 你能用一些证据证明吗? SQL Server 通常非常聪明地不重复工作(事实上,如果不是,CTE 方法不会保存它)。
  • 更多次 Count() 函数执行。性能下降。在您的第一种方法中,Count() 执行了四次。而在第二种方法中,它只执行了 2 次。
  • @Yaseen 仅仅因为您多次提到 COUNT() 函数并不意味着它会执行多次,而且当您使用 CTE 时,它并不神奇地意味着它不会执行多次。你试过了吗?对于所有三个查询,我得到完全相同的执行计划,具有相似的时间/CPU 和相同的 I/O。同样,请提供一些证据证明查询的执行方式会有所不同,而不是仅仅假设它们会因为您计算表达式而有所不同。
  • @Yaseen 这根本不是真的。可以从执行计划中验证同一个表达式只执行一次
【解决方案2】:
SELECT TT.ID,TT.CountData1,TT.CountData2,
CASE WHEN TT.CountData1>= 4 and TT.CountData2>=4 THEN 1 ELSE 2 END CODE
FROM
(SELECT ID,
COUNT(Data1) AS CountData1,
COUNT(Data2) AS CountData2
FROM 
   Table
GROUP BY 
 ID)TT;

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 2022-01-10
    • 2012-01-01
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    相关资源
    最近更新 更多