在SQL中选择CASE与CASE

Cas*_*jne 7 t-sql sql-server sql-server-2008

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

以某种方式不正确但工作语法,返回错误结果,例如,0当比较在两个相等的值上完成时返回:

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

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

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

甚至更简单:

(SELECT CASE 
    WHEN 
       X = Y 
    THEN 1 ELSE 0 END
) AS Result
Run Code Online (Sandbox Code Playgroud)

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

(CASE 
    WHEN 
       X = Y 
    THEN 1 ELSE 0 END
) AS Result
Run Code Online (Sandbox Code Playgroud)

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

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

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

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 
Run Code Online (Sandbox Code Playgroud)

userComputerIsCompatible结果也是如此

Bog*_*ean 6

我认为这种行为的原因是下一个:类似的表达式(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])表达式的 执行计划在此输入图像描述

我看到Constant Scan(扫描一个常量的内部表)运算符而不是Clustered Index Scanbefore SegmentStream Aggregate([Expr1007] = Scalar Operator(SUM(@OrderHeader.[IsWeb] as [h].[IsWeb])))运算符.此内部表(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;
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)