SQL按位查询以提取多天的事件,同时遵守其他"过滤器"

时间:2012-04-19 13:08:56

标签: sql sql-server-2008

我正在尝试构建一个查询,该查询将根据一系列过滤器从数据库中提取事件:baseId,title,age,以及它将发生的天数。

这是我到目前为止所得到的:

SELECT * FROM [Events]
WHERE BaseId = 574 AND Title LIKE '%occurs%' AND MinAge <= 5 AND MaxAge >= 5 
AND (FreqType = 8 AND (FreqInterval & 2) = 2) 
OR (FreqType = 8 AND (FreqInterval & 4) = 4)

没有OR线,它拉得很好。使用OR行,它不再关心BaseId,Title,MinAge和MaxAge列。嗯,它确实如此,但只有在OR为......之后它会在OR之后拉出所有匹配(不管以前的AND语句)。

如何让查询按每列过滤,然后按我想要的每个FreqInterval过滤?我可能不只是2,4 ...可以有1,2,4,8,16,32或64的任意组合。

或者,有没有办法使用FreqInterval的SUM进行AND (FreqType = 8 AND (FreqInterval & 6) = 6)?我不完全理解按位查询。

4 个答案:

答案 0 :(得分:3)

添加括号:

SELECT * FROM [Events]
WHERE BaseId = 574 AND Title LIKE '%occurs%' AND MinAge <= 5 AND MaxAge >= 5 
AND 
(
   (FreqType = 8 AND (FreqInterval & 2) = 2) 
   OR (FreqType = 8 AND (FreqInterval & 4) = 4) 
)

OR的运算符优先级低于AND,您应该在它们周围加上括号。您可以进一步简化它:

   (FreqType = 8 
       AND ( (FreqInterval & 2) = 2 OR (FreqInterval & 4) = 4) )
   )

正如你的建议,它几乎是正确的,但这是正确的:

 (FreqType = 8 
       AND (FreqInterval & 6) <> 0 )

顺便说一下,运算符优先级的另一个术语是运算符粘性,如果要明确写出原始查询,则为:

SELECT * FROM [Events]
WHERE 
( 
  BaseId = 574 AND Title LIKE '%occurs%' AND MinAge <= 5 AND MaxAge >= 5 
  AND (FreqType = 8 AND (FreqInterval & 2) = 2) 
)

OR 

(FreqType = 8 AND (FreqInterval & 4) = 4)

这类似于4 * 3 + 5,乘法的优先级高于加法,因此3分为4而不是5,因此输出为17。如果您的目标是输出32,则应明确指出3到5,将括号括在3和5左右,即4 * (3 + 5)

因此,在您使用OR的查询中,为了使它们粘在一起,请在它们周围加上括号。

尽管如此,就像你暗示的那样,我更喜欢这个ツ

 (FreqType = 8 AND (FreqInterval & 6) <> 0 )

答案 1 :(得分:2)

这与按位逻辑无关。您只需要修复WHERE子句,使用括号使两个按位比较成为同一评估集的一部分:

...
AND (FreqType = 8 AND (FreqInterval & 2) = 2 OR 
                       FreqInterval & 4) = 4))

您也不需要检查FreqType两次,所以我为您简化了这一点。

OR表示可以忽略任何先前的标准。将其放在括号中并使用其他按位检查意味着其中一个必须返回true。

答案 2 :(得分:2)

我认为这是一个优先问题。你在做:

BaseId = 574 AND Title LIKE '%occurs%' AND MinAge <= 5 AND MaxAge >= 5 AND (FreqType = 8 AND (FreqInterval & 2) = 2) 
OR
(FreqType = 8 AND (FreqInterval & 4) = 4)

尝试添加额外的()

WHERE BaseId = 574 AND Title LIKE '%occurs%' AND MinAge <= 5 AND MaxAge >= 5 
AND ((FreqType = 8 AND (FreqInterval & 2) = 2) OR (FreqType = 8 AND (FreqInterval & 4) = 4))

答案 3 :(得分:2)

SELECT * FROM [Events]
WHERE BaseId = 574 AND Title LIKE '%occurs%' AND MinAge <= 5 AND MaxAge >= 5 
AND ((FreqType = 8 AND (FreqInterval & 2) = 2) 
OR (FreqType = 8 AND (FreqInterval & 4) = 4))