2012-04-23 123 views
5

我有这条线在我的SQL查询:SQL查询的WHERE子句

WHERE client = $id 
    AND (isinvoiced = 0) OR (isinvoiced = 1 and isrecurring = 1) 

其得到更多的结果,比我期待的。不过,如果我这样写:

WHERE client = $id 
    AND (isinvoiced = 0) OR (isinvoiced = 1 and isrecurring = 1 and client = $id) 

然后它得到我想要的结果,但这是写这个最好的方法吗?我只是不想再遇到这个代码的更多问题。

+1

Google for [Distributivity rewrite rules](http://en.wikipedia.org/wiki/Distributivity)。 – onedaywhen 2012-04-23 15:32:37

+2

你确定你明白'a AND b OR c'和'a AND(b OR c)'的区别吗?你的例子更清楚地写成'(a AND b)或c',而不是你真正想要的。 – MatBailie 2012-04-23 15:38:08

回答

8

围绕整个AND子句,您需要多一组()。这说明client = $id必须是真实的,其他条件中的任何一个也必须是我= isinvoiced = 0isinvoiced = 1 and isrecurring = 1的组合。

WHERE client = $id 
    AND ((isinvoiced = 0) OR (isinvoiced = 1 and isrecurring = 1)) 
+0

完美的迈克尔,多数民众赞成我正在寻找,再次感谢......我会投票给你的答案,当它让我。 – user979331 2012-04-23 15:27:34

+1

如果'isinvoiced = 1'与'isinvoiced = 0'正好相反(即'isinvoiced'不能包含其他值,也不包含'NULL'),则可以进一步简化:WHERE client = $ id AND isinvoiced = 0或isrecurring = 1)'。 – 2012-04-24 05:06:57

1
where client = $id 
    and (
     isinvoiced = 0 
     or (
      isinvoiced = 1 
      and isrecurring = 1 
      ) 
     ) 
-1

如果where子句

remove -> WHERE client = $id 

,只是有

WHERE (isinvoiced = 0) OR (isinvoiced = 1 and isrecurring = 1 and client = $id) 

这是否让你的结果你想删除初始?

+0

OP要始终匹配“客户端”。看到接受的答案。 – Ben 2012-04-23 21:35:08

2

添加括号在你AND条款:

WHERE client = $id 
    AND ((isinvoiced = 0) OR (isinvoiced = 1 and isrecurring = 1)) 
1

你想要的是这样的:

WHERE client = $id AND ((isinvoiced = 0) OR (isinvoiced = 1 and isrecurring = 1)) 

如果你不把多余的blaquets它将使一个OR与客户restiction并给出更多结果。

0

关于SQL,您应该旨在编写搜索条件conjunctive normal form(“AND条款的一个系列”)。有各种rewrite rules来协助这一点。

distributive rewrite law在这种情况下有用即

(P AND Q) OR R <=> (P OR R) AND (Q OR R)  

你的情况:

(isinvoiced = 0) OR (isinvoiced = 1 AND isrecurring = 1) 

可改写为:

(isinvoiced = 0 OR isinvoiced = 1) AND (isinvoiced = 0 OR isrecurring = 1) 

因此,无需笨重的整个搜索条件parens:

.... 
WHERE client = $id 
     AND (isinvoiced = 0 OR isinvoiced = 1) 
     AND (isinvoiced = 0 OR isrecurring = 1);