sql server中的按位和逻辑

时间:2014-12-15 13:57:32

标签: sql sql-server math bitwise-operators bitwise-and

我有一个表,它在一个整数列中存储标志值。(我不是设计师)

我有一个查询,其中一个where条件是

旗帜& 256 == 0

对于第8位不是1的所有无符号数,上述条件为真。

问题是,在sql server中,在将int转换为二进制时,它占用了太多时间,并且查询的性能因很多其他连接而降低。

有没有办法用一个简单的信息取代上述条件?

1 个答案:

答案 0 :(得分:2)

根据您的说法,我认为您想用可搜索的运营商表达flags & 256

如果您的标志是最常用的位之一(即使用8位以上的位),这将更容易。为此,我们需要记住,在b位上写的数字的值介于0和2之间 b -1。

标志值

上第8位的含义
  • 如果第8位是最常用的,那么表示为数字的标志的值介于0和511之间。然后,flags & 256 > 0等同于flags >= 256,这是微不足道的,因为未设置第8位的任何二进制数是7位的数字,因此其值介于0和255之间。

  • 理想情况下,为了在没有位掩码的情况下表达这一点,我们希望(flags % 512) >= 256,但我怀疑它也不会受到攻击。因此,对于第8个以上的每个可能的标志组合,我们将需要枚举设置第8位的间隔。如果只使用1或2,则很容易,否则会更难。

10位

的间隔示例

假设你使用10位作为标志,那么你的位可以用00,01,10或11作为前缀。因为它们是位10和9,相应的数字(假设这些前缀后缀为8个零)是0,512,1024和1536。

因此,'标志的所有值的间隔都是' 第8位未设置是:

  • [0255]
  • [512767]
  • [1024,1279]
  • [1536,1791]

因此flag & 256 == 0相当于flags BETWEEN 0 AND 255 OR flags BETWEEN 256 AND 511 OR flags BETWEEN 512 AND 767 OR flags BETWEEN 768 AND 1023

推广间隔

假设您有可能的F标志(也就是使用的位数),并且您对标志C(因此该位的位置)感兴趣。

标志设置为1的间隔是,对于所有i< 2 F-C ,[(2i + 1)2 C ,(2i + 2)2 C -1]

标志设置为0的间隔是,对于所有i< 2 F-C ,[(2i)2 C ,(2i + 1)2 C -1]

如您所见,您需要考虑2个 F-C 间隔。因此,如果有可能贿赂设计你的SQL数据库的人,让他把那个标志作为最大可能:F = C,你只需要一个标记来处理。

这是一个快速的&脏bash脚本将为您编写丑陋的interval子句:

#!/usr/bin/env bash

bits=10 # F, total number of possible flags
check=8 # C, position of the flag

grain=$(( 2 ** check ))
interval_offsets="$(seq 0 $grain $(( 2 ** bits -1 )) )"


str=
for i in $interval_offsets 
do str="$str OR flags BETWEEN $(( i )) AND $(( i + grain - 1))"
done

echo "intervals for bit $check NOT set : ${str# OR}"


str=
for i in $interval_offsets 
do str="$str OR flags BETWEEN $(( i + grain )) AND $(( i + 2 * grain - 1))"
done

echo "intervals for bit $check set : ${str# OR}"