我不太明白为什么这两个不同的代码示例会返回不同的值。
以某种方式不正确但工作语法,返回错误结果,例如,当通过两个相等的值进行比较时,它返回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且Y = 22 =>结果= 0
(CASE
WHEN
X = Y
THEN 1 ELSE 0 END
) AS Result
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
所以userComputerIsCompatible
是有问题的结果
答案 0 :(得分: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])
表达式的执行计划
我在Clustered Index Scan
和Segment
(Stream Aggregate
)运算符之前看到Constant Scan
(Scan an internal table of constants)运算符而不是[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;
结果:
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 :(得分:1)
我尝试了你的代码,我得到了两个查询相同的结果。这是我试过的代码:
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
结果是 1 和 1
我是在SQL Server 2008 R2上运行的