加入收藏 | 设为首页 | 会员中心 | 我要投稿 温州站长网 (https://www.0577zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql-server – 在仅使用文字值的WHERE子句中替换ISNULL()的不同

发布时间:2021-01-09 06:00:40 所属栏目:MsSql教程 来源:网络整理
导读:副标题#e# 这不是什么: 这不是关于接受用户输入或使用变量的catch-all queries的问题. 这严格来说,在WHERE子句中使用ISNULL()将NULL值替换为canary值以与谓词进行比较,以及在SQL Server中将这些查询重写为SARGable的不同方法. 你为什么不在那边坐? 我们的

Table 'Users'. Scan count 20,logical reads 17564,lob read-ahead reads 0.
Table 'Workfile'. Scan count 0,lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 4844 ms,elapsed time = 863 ms.

重写交叉适用于派生连接会产生完全相同的一切.我不打算重新发布查询计划和统计信息 – 它们确实没有改变.

SELECT COUNT(u.Id)
FROM dbo.Users AS u
JOIN 
(
    SELECT u.Id
    FROM dbo.Users AS u
    WHERE u.Age < 18

    UNION ALL

    SELECT u.Id
    FROM dbo.Users AS u
    WHERE u.Age IS NULL
) x ON x.Id = u.Id;

关系代数:
为了彻底,并让Joe Celko不要困扰我的梦想,我们至少需要尝试一些奇怪的关系.这里没什么’!

尝试使用INTERSECT

SELECT COUNT(*)
FROM dbo.Users AS u
WHERE NOT EXISTS ( SELECT u.Age WHERE u.Age >= 18
                   INTERSECT
                   SELECT u.Age WHERE u.Age IS NOT NULL );

Table 'Users'. Scan count 1,lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 1094 ms,elapsed time = 1090 ms.

这是除了以外的尝试

SELECT COUNT(*)
FROM dbo.Users AS u
WHERE NOT EXISTS ( SELECT u.Age WHERE u.Age >= 18
                   EXCEPT
                   SELECT u.Age WHERE u.Age IS NULL);

Table 'Users'. Scan count 7,logical reads 9247,lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2126 ms,elapsed time = 376 ms.

可能还有其他方法来编写这些,但我会把这个留给那些可能比我更常使用EXCEPT和INTERSECT的人.

如果你真的需要一个计数
我在查询中使用COUNT作为一些简写(读:我有时懒得想出更多涉及的场景).如果你只需要一个计数,你可以使用CASE表达式做同样的事情.

SELECT SUM(CASE WHEN u.Age < 18 THEN 1
                WHEN u.Age IS NULL THEN 1
                ELSE 0 END) 
FROM dbo.Users AS u

SELECT SUM(CASE WHEN u.Age < 18 OR u.Age IS NULL THEN 1
                ELSE 0 END) 
FROM dbo.Users AS u

它们都具有相同的计划并具有相同的CPU和读取特性.

Table 'Users'. Scan count 1,lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 719 ms,elapsed time = 719 ms.

获胜者,冠军?
在我的测试中,在派生表上使用SUM的强制并行计划表现最佳.是的,许多这些查询都可以通过添加一些过滤索引来解决这两个谓词来辅助,但我想给其他人留下一些实验.

SELECT SUM(Records)
FROM 
(
    SELECT 1
    FROM dbo.Users AS u
    WHERE u.Age < 18

    UNION ALL

    SELECT 1
    FROM dbo.Users AS u
    WHERE u.Age IS NULL
) x (Records)   
OPTION(QUERYTRACEON 8649);

谢谢!

(编辑:温州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读