【问题标题】:SELECT CASE vs. CASE IN SQLSELECT CASE 与 SQL 中的 CASE
【发布时间】:2011-11-04 18:12:38
【问题描述】:

我不太明白为什么这两个不同的代码示例返回不同的值。

某种不正确但有效的语法,返回错误的结果,例如,当比较两个相等的值时返回0

(SELECT CASE 
    WHEN 
       SUM(V.IsCompatible) OVER 
          (PARTITION BY ComputerName, UserID) = ApplicationCount 
    THEN 1 ELSE 0 END
) AS CompatibleUser

下面的返回正确的值,即。 1 当有两个相等的值比较时。

(CASE 
    WHEN 
       SUM(V.IsCompatible) OVER 
         (PARTITION BY ComputerName, UserID) = ApplicationCount 
    THEN 1 ELSE 0 END
) AS CompatibleUser

甚至更简单:

(SELECT CASE 
    WHEN 
       X = Y 
    THEN 1 ELSE 0 END
) AS Result

X = 22 AND Y = 22 => 结果 = 0

(CASE 
    WHEN 
       X = Y 
    THEN 1 ELSE 0 END
) AS Result

X = 22 AND Y = 22 => 结果 = 1

我了解应用正确的语法很重要,并且我知道 T-SQL 中的 SELECT CASE 语法,但我不明白如何评估 第一个代码示例 strong> 并提供了意想不到的结果。

更新:上下文中的完整查询

select userapplication.username,
   computerdetails.computername,
   sum(userapplication.iscompatible) 
       over (partition by computerdetails.computername, 
                          userapplication.userid) as compatiblecount,
   userapplication.applicationcount,
   ( case
       when sum(userapplication.iscompatible) 
           over (partition by 
           computerdetails.computername, 
           userapplication.userid) <> userapplication.applicationcount 
       then 0
       else 1
     end 
   ) as usercomputeriscompatible
from   computerdetails
   right outer join usercomputer
     on computerdetails.computerid = usercomputer.computerid
   right outer join userapplication
     on usercomputer.gebruikerid = userapplication.userid 

所以userComputerIsCompatible 是这里有问题的结果

【问题讨论】:

  • 您可能需要显示更多查询。这些样本是否用于SELECT 子句、WHERE 子句、HAVING 子句或其他地方?
  • 我添加了查询(命名略有修改),但它代表了它的工作方式

标签: sql-server sql-server-2008 tsql


【解决方案1】:

我认为这种行为的原因是下一个:像(SELECT ...) 这样的表达式被认为是子查询,即使它们没有FROM 子句。假设这些(错误)“子查询”的数据源只是当前行。因此,(SELECT expression) 被解释为(SELECT expression FROM current_row)(SELECT SUM(iscompatible)OVER(...)) 被执行为(SELECT SUM(iscompatible)OVER(current_row))

参数:分析(SELECT SUM(IsWeb) OVER(PARTITION BY OrderDate) [FROM current_row]) 表达式的执行计划

我在SegmentStream Aggregate ([Expr1007] = Scalar Operator(SUM(@OrderHeader.[IsWeb] as [h].[IsWeb]))) 运算符之前看到Constant Scan (Scan an internal table of constants) 运算符而不是Clustered Index Scan。此内部表 (Constant Scan) 是从当前行构造的。

示例(使用 SQL2005SP3 和 SQL2008 测试):

DECLARE @OrderHeader TABLE
(
     OrderHeaderID  INT IDENTITY PRIMARY KEY
    ,OrderDate      DATETIME NOT NULL
    ,IsWeb          TINYINT NOT NULL --or BIT
);
INSERT  @OrderHeader 
SELECT  '20110101', 0
UNION ALL 
SELECT  '20110101', 1
UNION ALL
SELECT  '20110101', 1
UNION ALL 
SELECT  '20110102', 1
UNION ALL
SELECT  '20110103', 0
UNION ALL
SELECT  '20110103', 0;

SELECT  *
        ,SUM(IsWeb) OVER(PARTITION BY OrderDate) SumExpression_1
FROM    @OrderHeader h
ORDER BY h.OrderDate;

SELECT  *
        ,(SELECT SUM(IsWeb) OVER(PARTITION BY OrderDate)) SumWithSubquery_2
FROM    @OrderHeader h
ORDER BY h.OrderDate;

结果:

OrderHeaderID OrderDate               IsWeb SumExpression_1
------------- ----------------------- ----- ---------------
1             2011-01-01 00:00:00.000 0     2
2             2011-01-01 00:00:00.000 1     2
3             2011-01-01 00:00:00.000 1     2
4             2011-01-02 00:00:00.000 1     1
5             2011-01-03 00:00:00.000 0     0
6             2011-01-03 00:00:00.000 0     0

OrderHeaderID OrderDate               IsWeb SumWithSubquery_2
------------- ----------------------- ----- -----------------
1             2011-01-01 00:00:00.000 0     0
2             2011-01-01 00:00:00.000 1     1
3             2011-01-01 00:00:00.000 1     1
4             2011-01-02 00:00:00.000 1     1
5             2011-01-03 00:00:00.000 0     0
6             2011-01-03 00:00:00.000 0     0

【讨论】:

  • +1 同意,SELECT SUM(IsWeb) OVER(PARTITION BY OrderDate) 显然只是应用于当前行的列,因此无论IsWeb 的值在该行中是什么,它都将始终具有。
【解决方案2】:

我尝试了您的代码,两个查询的结果相同。这是我尝试过的代码:

DECLARE @X INT = 22
DECLARE @Y INT = 22

SELECT (SELECT CASE 
    WHEN 
       @X = @Y 
    THEN 1 ELSE 0 END
) AS Result

SELECT (CASE 
    WHEN 
       @X = @Y 
    THEN 1 ELSE 0 END
) AS Result

结果是 11

我在 SQL Server 2008 R2 上运行了这个

【讨论】:

  • +1:我自己也做了同样的事情,结果确实是相等且正确
  • 在我看来,真正的问题不是CASE ... END,而是SUM(V.IsCompatible)在这两种情况下的计算方式:(SELECT SUM... no_FROM_clause)(SUM...)
猜你喜欢
  • 2015-02-27
  • 2012-05-10
  • 2021-11-26
  • 2021-03-31
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
相关资源
最近更新 更多