2013-10-05 35 views
1

我有一个过滤器,用户可以选择操作,例如包含,等...否定SQL WHERE条件可空场

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

现在我已经添加了失活突变体 - 不含,等等。我不希望重写了整个WHERE条件,所以我在前面加上NOT到已经存在的:

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

但是,有一个问题。如果布尔是一个可为空的字段,它实际上有NULL,那么负的WHERE条件不会选择它,尽管从人类的角度来看(与SQL相反)NULL值应该满足布尔不是xoxo filter 。

我通过修改原有的积极解决这个问题WHERE条件是这样的:

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

然后,否定收率:

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

而这一次NULL值正确拾取。同样的问题是包含过滤器。

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

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

P.S.

请注意,我想表达是形式不积极的。

回答

1

我想你应该能够使用COALESCE到您的空值转换为空字符串闪避:

-- 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

+0

+1。问题 - 使用COALESCE比我所做的更有效吗? – mark

+0

我认为COALESCE会相同或接近,以至于不会产生任何可衡量的差异。 –