经常需要生成查询,其中筛选条件是动态确定的——值列表由用户界面提供,而缺失值(NULL)也必须能够进入或不进入结果。这样的查询必须在大数据量下快速执行并在SQL语义上是正确的。
不正确地组合条件IN,NOT IN和NULL检查会导致意外结果,因为在SQL中表达式"NULL IN (...)"始终返回UNKNOWN,而"NOT IN"可能导致空结果,如果列表中的任何元素是NULL。对于大数据而言,条件写得不好时,性能可能急剧下降。
正确的组合方式如下:
SELECT * FROM sales WHERE region IN ('Moscow','Samara') OR region IS NULL;
SELECT * FROM sales WHERE (region NOT IN ('Moscow','Samara') OR region IS NULL);
SELECT * FROM sales WHERE region NOT IN ('Moscow','Samara') AND region IS NOT NULL;
关键特点:
如果检查"WHERE field NOT IN ('a', NULL)"会发生什么?
结果始终为空,因为任何行与列表中的NULL比较会导致UNKNOWN,从而过滤掉所有行。
代码示例:
SELECT * FROM test WHERE name NOT IN ('Ivan', NULL);
"IN (NULL,...)"会为NULL的行返回值吗?
不会。表达式NULL IN (...)始终返回UNKNOWN,而不是TRUE。
如何加速对大型值列表的筛选?
使用索引,并优先使用临时表的JOIN,如果列表很大(数百/数千个值)——这比使用长IN语句更快。
在分析报告中应用了"WHERE city NOT IN ('London', field_2, NULL)"。结果完全为空,没人能及时理解丢失行的原因。
优点:
缺点:
在CRM中选择了客户地区列表并添加了"包含缺失值"的额外按钮。筛选逻辑:
... WHERE city IN ('SPB','NNov') OR city IS NULL
优点:
缺点: