postgreSQL查询中的可选条件

postgreSQL查询中的可选条件,sql,postgresql,Sql,Postgresql,我需要创建一个带有可选参数的过程,并且仅当它们不为null时才使用它们 我当前的查询如下所示: SELECT * FROM sth WHERE (arg1 IS NULL OR sth.c1 = arg1) AND (arg2 IS NULL OR sth.c2 = arg2) AND (arg3 IS NULL OR sth.c3 > arg3) AND (arg4 IS NULL OR sth.c4 < arg4) 我在想办法使它看起来更好/更短。我的第一个镜头

我需要创建一个带有可选参数的过程,并且仅当它们不为null时才使用它们

我当前的查询如下所示:

SELECT * FROM sth WHERE
  (arg1 IS NULL OR sth.c1 = arg1) AND
  (arg2 IS NULL OR sth.c2 = arg2) AND
  (arg3 IS NULL OR sth.c3 > arg3) AND
  (arg4 IS NULL OR sth.c4 < arg4)
我在想办法使它看起来更好/更短。我的第一个镜头是:

SELECT * FROM sth WHERE
  COALESCE(sth.c1 = arg1, 't') AND
  COALESCE(sth.c2 = arg2, 't') AND
  COALESCE(sth.c3 > arg3, 't') AND
  COALESCE(sth.c4 < arg4, 't');

但我不确定这看起来是否更好。你知道一些有用的技巧吗?

保持原样。使用coalesce将阻止查询计划器正确地执行其工作,最终将导致糟糕的查询计划

据我所知,以下表达式将使用btree索引:

col='val' col为空 以下表达式将不使用btree索引:

col是[不是]“val” col='val'为[非] col[不]与“val”不同 聚结菌落,'val'='val' coalescecol='val',
好的,我认为这个查询是实现这个目的的最好方法

SELECT * FROM sth WHERE
  NOT (sth.c1 = arg1) IS FALSE AND
  NOT (sth.c2 = arg2) IS FALSE AND
  NOT (sth.c3 > arg3) IS FALSE AND
  NOT (sth.c4 < arg4) IS FALSE;

所以,如果表达式为true或null,它将返回trueNULL@nrathaus:anything=NULL为空第一种形式可能更清晰,并且让优化者通过证明OR的另一面始终为真来完全删除表达式。尽管计划者可能能够证明[anything]=NULL也总是NULL;我还没查过;您应该能够在解释输出中进行说明。我更新的查询如何?在这种情况下,查询计划器能否正常工作?据我所知,您的第一个查询计划器是它将尝试优化的唯一查询计划器。@Adassko显示的一个可能看起来更好一些,但是使用IS操作符有点像使用COALESCE:规划者通常会产生一个seq扫描。对于原始查询,它至少应该做一次位图索引扫描,很可能它实际上会以不同的方式正确地准备,就像根据输入参数进行简化一样。但是第一次查询中不也使用IS运算符吗?@Denis规划师确实通过合并进行了优化;合并“非空”,选择。。。甚至不会计划子查询。我不确定它是否证明x=NULL总是空的,并且避免计算第一项。@CraigRinger:我很想知道在哪里或如何…从coalescid=5的测试中选择*和从coalescid=5的测试中选择*都会在9.3.1中产生一个序列扫描。在第9.3页,解释分析从测试中选择*,其中notid=5为false=>seq scan+filter。解释分析从测试中选择*,其中id=5或5为null=>索引扫描。
1.
true = true // true
true = false // false
true = null // null

2.
false is false // true
true is false // false
null is false // false

3.
not true // false
not false // true