sql - 使用可为空字段否定 SQL WHERE 条件

标签 sql postgresql where-clause nullable

我有一个过滤器,用户可以在其中选择包含等操作...

  • 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%'

当然,如果您正在搜索空字符串,这种欺骗会遇到问题,在这种情况下,您将需要一个上下文敏感的标记值,以便您可以智能地选择可能与您的搜索词不匹配的内容.

演示:http://sqlfiddle.com/#!12/8bbd2/3

关于sql - 使用可为空字段否定 SQL WHERE 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19197738/

相关文章:

mysql - Laravel - 如何在这里分页?

sql - 在哪里放置主键

SQL ON DELETE CASCADE 与删除业务逻辑

sql - Mysql 语句不适用于多个 AND 子句

sql - WHERE 和 AND 子句不返回值

SQL 服务器 : Transpose Rows to Columns (n:m relationship)

MySQL - 使用单次更新保存列表顺序

PostgreSQL "tuple already updated by self"

sql - 数据结构,不想将列表存储为文本

mysql - 在 where 子句中使用 if 语句