2012-06-12 53 views
1

我已经构建了一个接口,用户从数据库中获取记录。用户可以选择指定0个或更多的过滤器。有四种过滤器A,B,C,d(让我们说的这些都是在某个表中的字段)构建动态无失败where子句

这里是我的查询应该是什么样子:

select * from table 
where (A = v1 or B = v2 or C = v3) and D = v4 

我想拿出一个办法来制定查询,而当指定了特定的过滤器时,则应用该查询,否则将被忽略。但这应该适用于所有16个案例。

我已经能够拿出迄今这些方法是:

select * from table 
where (
    (A = v1 and 1) 
    or (B = v2 and 1) 
    or (C = v3 and 1) 
    ) 
    and D = v4 

v1或其它值设置为-1未指定,当他们。因此,如果没有指定它们,它们会被忽略,因为使用另一个过滤器(来自A,B,C之间)。但是,在没有指定A,B和C的情况下,这会失败。在这种情况下,假使用D来结束,并且不应用D.

有没有一种方法来与这种情况下的where子句?我也接受这个程序的解决方案,我通过代码添加或不添加子句,但我更喜欢这种方式。我真的不想有很多if-else语句。

谢谢!

回答

1

怎么样使用case构建

select * 
    from table 
    where (A = CASE WHEN v1 IS NOT NULL THEN v1 else '' END) 
      OR (B = CASE WHEN v2 IS NOT NULL THEN v2 else '' END) 
      OR (C = CASE WHEN v3 IS NOT NULL THEN v3 else '' END) 
      OR (CASE WHEN v1 is null and v2 is null and v3 is null then 1 else 0 end) 
    and D = v4 
+0

+1尼斯一个,复制这个想法告诉了我答案 – Andomar

+0

所以,当A和B被指定,而C不是时,C = C给出了我的真实性,并且A或B或真实结果在A和B中没有得到应用,所有的行都将被考虑。 –

+0

@Caffeine Yeap。同意。我更新了SQL。我假设A,B,C是varchar字段。 –

0

数据库也很难优化动态where子句。通常情况下,他们会为第一次调用生成最优的计划。因此,如果您的第一次搜索是针对过滤器A和B,则查询计划将针对此进行优化。即使使用过滤器C和D,下一个查询也将使用该计划。添加代码中的where子句往往会表现得更好。

但它是可能的,例如:

where (
      A = @FilterAValue 
      or B = @FilterBValue 
      or C = @FilterCValue 
     ) 
     and D = coalesce(@FilterDValue, D) 

然后您可以切换与FilterXValue参数的过滤器。如果A,B或C的过滤器为null,则仍会评估or的其他部分。 A = null or B = 1unknown or B = 1相同,只有当B = 1时才是如此。

+0

当A,B,C没有提供时会发生什么?如果我没有错,那OP是在找什么。 –

+0

然后没有行返回(与您的答案相同)。您可以添加'或@FilterAValue为null,并且@FilterBValue为null并且@FilterCValue为null'在最后一个'或'下面返回所有行。 – Andomar

+0

最后一种情况检查v1,v2,v3是否为null,然后它将对所有行返回true,从而仅应用D仅滤波器。或者可能是我得到的问题是错的:-) –

0

如果v1 - v4是你正在寻找的价值和所有的人都-1如果没有指定,你可以这样做:

SELECT 
    * 
FROM 
    table 
WHERE 
    (
    (A = v1 OR -1 = v1) 
    or 
    (B = v2 OR -1 = v2) 
    or 
    (C = v3 OR -1 = v3) 
) 
AND 
    (D = v4 OR -1 = v4) 
+0

假设我指定了A和B,但不是C.在这种情况下,它将是 (A = v1或B = v2或true)和D = v4,它将有点丢弃前两个过滤器。 –