use*_*347 0 sql-server case query-performance
SELECT x, y, z,
CASE
WHEN COUNT (PH.header_id) OVER (PARTITION BY PL.header_id)
NOT IN (null,0) THEN L_Count
ELSE COUNT (PH.header_id) OVER (PARTITION BY PL.header_id)
END as quantity
Run Code Online (Sandbox Code Playgroud)
有没有更有效的写法?
我非常清楚它在一张大桌子上执行了两次计数。
不幸的是,我无法发布查询计划,因为我正在使用的用户帐户正在等待 SHOWPLAN 权限。
NOT IN 子句是一个附带问题。感谢您提供有关改进方法的评论反馈,但问题的焦点是重复计数。
这里有两个问题:
对于第一个,我们可以通过仅计算该表达式一次来解决整洁方面的问题(并且我将从NOT IN (NULL, 0)
逻辑更改为仅检查计数是否大于 0(这消除了 NULL 和 0):
;WITH x AS
(
SELECT x, y, z, L_Count,
q = COUNT (PH.header_id) OVER (PARTITION BY PL.header_id)
FROM ...something PH and PL...
)
SELECT x, y, z, quantity = CASE WHEN q > 0 THEN L_Count ELSE q END
FROM x;
Run Code Online (Sandbox Code Playgroud)
这是否是正确的或最有效的分区选择是另一回事。
对于第二个问题,SQL Server 非常聪明,可以在给定范围内仅执行一次计算。如上所述,引用一个表达式两次并不一定意味着它将被计算两次,并且像我在这个答案中所做的那样将第二个引用隐藏在 CTE 中也不能保证它会被精确计算一次。为了确定,您必须检查执行计划和其他详细信息(例如 Plan Explorer 提供的表达式选项卡和性能指标)并进行比较。
拥有表结构、示例数据和所需结果(甚至更多查询)确实有助于为您创建更好的(且经过验证的)解决方案。我只是建议您在问题中使用相同的逻辑,我只能假设它现在对您有用(我试图理解您的CASE
逻辑甚至意味着什么 - 它似乎在说“如果有一个有效的计数此窗口函数,然后使用另一列,但如果此窗口函数没有有效计数,则使用无效计数”)。我怀疑翻译/简化过程中丢失了一些东西。
也可以看看: