Ico*_*ood 27 mysql sql sql-server
SELECT id FROM customers WHERE type IS NOT Null;
Run Code Online (Sandbox Code Playgroud)
与:
SELECT id FROM customers WHERE NOT type IS NULL;
Run Code Online (Sandbox Code Playgroud)
上述任何一个都将返回的数据将完全相同.
有什么区别,为什么其中一个会更好?
编辑:
在我看来,在性能方面可能会有所不同.有人关心这个吗?
Qua*_*noi 32
没有区别.
在我看来,在性能方面可能会有所不同.有人关心这个吗?
所有主要搜索引擎(即MySQL
,SQL Server
,Oracle
和PostgreSQL
)将合并在分析阶段,从他们制作计划相同,这些谓词.
处理这些条件比仅仅按一个或另一个顺序应用操作员更复杂.
例如,在Oracle
中,IS NOT NULL
(或NOT IS NULL
)条件意味着使用索引,所以这样的查询的可能性:
SELECT column
FROM mytable
WHERE column IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
很可能会用a执行index fast full scan
,而不会在运行时进行额外的检查(因为这些NULL
值不会进入索引,因此检查它们没有用).
即使需要检查每条记录,检查的顺序也将由优化器定义(而不是谓词和运算符出现在WHERE
子句中的顺序).
例如,这是一个Oracle
查询计划:
SQL> EXPLAIN PLAN FOR
2
2 SELECT *
3 FROM t_test
4 WHERE NOT column IS NULL
5 /
Explained
SQL> SELECT *
2 FROM TABLE(DBMS_XPLAN.display())
3 /
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 958699830
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 30 | 1260 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T_TEST | 30 | 1260 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLUMN" IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它filter
被内部翻译成了一个IS NOT NULL
(Oracle
与大多数评论者一起似乎认为是更合适的形式)
更新:
正如乔纳森·莱弗勒所指出的那样,这些在评估元组时是不同的(而不是单列).
由混合值NULL
和非NULL
值组成的元组既不是a NULL
也不是a NOT NULL
.
在PostgreSQL
(它支持这个对元组的谓词)中,这两个表达式:
SELECT (1, NULL) IS NULL
SELECT (1, NULL) IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
评价为假.
wup*_*tah 16
IS NOT NULL
是比较操作符,就像IS NULL
或=
,>
,<
等.
NOT
是一个逻辑运算符,作用于其余条件.所以你可以说NOT type = 5
,NOT type IS NULL
甚至是NOT type IS NOT NULL
.
我的观点是要指出它们是两个非常不同的运算符,即使结果是相同的.当然,在布尔逻辑中,NOT (column IS NULL)
和之间没有区别column IS NOT NULL
,但知道差异是明智的.
至于性能,IS NOT NULL
可能会节省几个周期,NOT ... IS NULL
因为您使用的是单个运算符而不是两个运算符,但任何合理的优化器都会发现它们在查询运行之前是相同的.
Jon*_*ler 12
在LHS术语是简单变量或表达式的通常情况下,NOT x IS NULL
和之间没有区别x IS NOT NULL
.优化器将对两者进行相同的处理.
但是,在完整的SQL中,LHS术语不仅限于简单的变量或表达式; 在正式语法中,LHS是<row value predicand>
:
§8.7
<null predicate>
(p395)指定空值的测试.
Run Code Online (Sandbox Code Playgroud)<null predicate> ::= <row value predicand> <null predicate part 2> <null predicate part 2> ::= IS [ NOT ] NULL
通过语法追逐,您会发现:
§7.2
<row value expression>
(p296)指定行值.
[...]
Run Code Online (Sandbox Code Playgroud)<row value predicand> ::= <row value special case> | <row value constructor predicand> <row value special case> ::= <nonparenthesized value expression primary>
和:
§7.1
<row value constructor>
(p293)指定要构造为行或部分行的值或值列表.
Run Code Online (Sandbox Code Playgroud)<row value constructor> ::= <common value expression> | <boolean value expression> | <explicit row value constructor>
[...]
Run Code Online (Sandbox Code Playgroud)<row value constructor predicand> ::= <common value expression> | <boolean predicand> | <explicit row value constructor>
所以它继续.(通过SQL标准追逐任何东西都是很难的.你可以在http://savage.net.au/SQL/找到一个高度超链接的标准版本.)
但是,正如您可能从提到的"行值"中猜到的那样,您可以在LHS上组合多个简单表达式以形成"行值构造函数谓词".然后两种形式之间存在差异.
从概念上讲,你有:
(val1, val2, val3) IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
VS
NOT (val1, val2, val3) IS NULL
Run Code Online (Sandbox Code Playgroud)
现在,在第一种情况下,如果val1,val2和val3中的每一个都不为NULL,则为TRUE.在第二种情况下,如果val1,val2,val3中的任何一个不为NULL,则为TRUE.因此,在某些情况下,这两种操作并不相同.
但是,正如我前面所说,对于简单的列或表达式的通常情况,两者之间没有区别.