1

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

  • bubu 是 xoxo翻译成WHERE lower(bubu) = 'xoxo'SQL WHERE 条件。
  • bubu 包含 xoxo转换为WHERE bubu ILIKE '%xoxo%'SQL WHERE 条件。

现在我添加了否定变体 - is notdoes not contain等。我不想从头开始重写 WHERE 条件,所以我NOT在已经存在的条件之前添加:

  • bubu 不是 xoxo转换为WHERE NOT lower(bubu) = 'xoxo'SQL WHERE 条件。
  • bubu 不包含 xoxo转换为WHERE NOT bubu ILIKE '%xoxo%'SQL WHERE 条件。

但是,有一个问题。如果bubu是一个可以为空的字段并且它实际上包含 NULL,那么否定的 WHERE 条件不会选择它,尽管从人类的角度(与 SQL 相对)来看,NULL 值应该满足bubu is not xoxo过滤器。

我通过修改原来的正 WHERE 条件来解决这个问题,如下所示:

  • bubu 是 xoxo翻译成WHERE (lower(bubu) = 'xoxo' AND bubu IS NOT NULL)SQL WHERE 条件。

然后,否定产生:

  • bubu 不是 xoxo转换为WHERE NOT (lower(bubu) = 'xoxo' AND bubu IS NOT NULL)SQL WHERE 条件。

而这一次 NULL 值被正确拾取。contains过滤器也存在同样的问题。

是否有更优雅的解决方案来解决人类如何处理 NULL 与 SQL 如何处理它之间的这种不一致?

我使用的是 PostgreSQL 9.2,我不介意有一个特定于这个数据库的解决方案。

附言

请注意,我希望否定表达式的形式为NOT positive

4

2 回答 2

1

我认为您应该能够使用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

于 2013-10-05T20:10:24.410 回答
0

对于=运算符,您可以使用is [not] distinct from构造

WHERE (lower(bubu) is not distinct from 'xoxo')

http://www.postgresql.org/docs/9.2/static/functions-comparison.html

于 2013-10-05T13:13:18.663 回答