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



我正在尝试构建一个查询,该查询将根据一系列过滤器从数据库中提取事件:baseId,标题,年龄和发生日期。

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

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 语句如何)。

如何让查询按每列进行筛选,然后按我想要的每个频率间隔进行筛选?我可能不止 2、4 个...可以有 1、2、4、8、16、32 或 64 的任意组合。

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

添加括号:

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 )

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

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

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

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

我认为这是一个优先问题。您正在执行的操作:

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

最新更新