MySQL 位运算和过滤器

9
我尝试使用MYSQL(如有必要,使用UDF)实现位过滤器。该过滤器类似于AND,但我想使用掩码来构建新的位字符串...让我用样本向您解释一下:
假设我有一个表,其中包含存储8位流的blob:
data1: 10110110 data2: 01100010 data3: 00010011
然后我有一个掩码,可以在mask值为1时应用以获取数据中的位:
MASK: 00101011
因此得到以下预期结果:
data1: 1010 data2: 1010 data3: 0011
是否有一种优化过滤的方法,而不必循环遍历“mask”中的每个位以获得“data”行中相应的值...
澄清:
我只是为了发布而取了8位,但它更像256字节。
为了澄清示例,掩码00101011被解释为:如果您从左到右阅读掩码,并从第1位到第8位进行枚举,则从数据字段的第3、5、7、8位获取位值...希望这个澄清是“清楚”的...

我看不出来那个掩码和那些行应该如何返回那些数据。 - Joe
在我看来,如果没有循环,实现这个任务会非常困难。 - Karolis
2个回答

8

您可以在MySQL中使用位运算符:

http://dev.mysql.com/doc/refman/5.0/en/bit-functions.html

例子:

SELECT (data1 & b'00101011') as output1 FROM ......

快速测试:

SELECT (b'10110110' & b'00101011') as output1

这将使用您指定的掩码的二进制模式进行按位 AND
有关更多示例,请参见上面的链接。

1
我认为这不是他想要的。 - Karolis

8
我知道的实现你想要的唯一方法是类似于:
SELECT ((data >> 2) & 8) | ((data >> 1) & 4) | (data & 3) FROM ...

显然,你需要根据你的掩码构建表达式;这并不是非常难做到,只是有点繁琐——你基本上需要在掩码中循环遍历每个位,如下所示:

var mask = 0b00101011;
var parts = new Array();
var shift = 0;
var unshift = 0;
while (mask > 0) {
    while ((mask & 1) == 0) {
        shift = shift + 1;
        mask = mask >> 1;
    }
    submask = 0;
    while ((mask & 1) == 1) {
        submask = submask + (1 << unshift);
        unshift = unshift + 1;
        mask = mask >> 1;
    }
    parts.push( "((data >> " + shift + ") & " + submask + ")" );
}
var expr = parts.join( " | " );
console.log(expr);

上面的示例代码是用JavaScript编写的,所以您可以在此处运行它并获得以下结果:

((data >> 0) & 3) | ((data >> 1) & 4) | ((data >> 2) & 8)

已在控制台记录,但将其移植到其他语言应该非常容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接