我有一个过滤器,用户可以在其中选择是、包含等操作...
- bubu is xoxo 翻译成
WHERE lower(bubu) = 'xoxo'
SQL WHERE条件。 - bubu contains xoxo 翻译成
WHERE bubu ILIKE '%xoxo%'
SQL WHERE条件。
现在我添加了否定变体 - 不是、不包含等。我不想从头开始重写 WHERE 条件,所以我在前面加上NOT
到已经存在的:
- bubu is not xoxo 翻译成
WHERE NOT lower(bubu) = 'xoxo'
SQL WHERE条件。 - bubu does not contain xoxo 翻译成
WHERE NOT bubu ILIKE '%xoxo%'
SQL WHERE条件。
但是,有一个问题。如果 bubu 是一个可为 null 的字段并且它实际上包含 NULL,那么否定的 WHERE 条件不会选择它,尽管从人类的角度(与 SQL 相反)NULL 值应该满足 bubu 不是 xoxo 过滤器。
我通过像这样修改原始的肯定 WHERE 条件来解决这个问题:
- bubu is xoxo 翻译成
WHERE (lower(bubu) = 'xoxo' AND bubu IS NOT NULL)
SQL WHERE 条件。
然后,否定产生:
- bubu is not xoxo 翻译成
WHERE NOT (lower(bubu) = 'xoxo' AND bubu IS NOT NULL)
SQL WHERE 条件。
这次 NULL 值被正确拾取。 contains 过滤器也存在同样的问题。
是否有更优雅的解决方案来解决人类处理 NULL 的方式与 SQL 处理 NULL 的方式之间的这种不一致?
我正在使用 PostgreSQL 9.2,我不介意有一个特定于该数据库的解决方案。
附言
请注意,我希望negative 表达式的形式为NOT positive。
最佳答案
我认为您应该能够使用 COALESCE将 NULL 转换为空字符串:
-- These skip skips NULLs
lower(coalesce(bubu, '')) = 'xoxo'
coalesce(bubu, '') ilike '%xo%'
-- These will find NULLs
not lower(coalesce(bubu, '')) = 'xoxo'
not coalesce(bubu, '') ilike '%xo%'
当然,如果您正在搜索空字符串,这种欺骗会遇到问题,在这种情况下,您将需要一个上下文敏感的标记值,以便您可以智能地选择可能与您的搜索词不匹配的内容.
关于sql - 使用可为空字段否定 SQL WHERE 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19197738/