MySql查询表掩码

时间:2013-06-27 17:04:01

标签: mysql bitmask

我有一张桌子,里面装满了各种各样的“面具”,如下所示:

Type    Mask1    Mask2    Mask3
0       fff      fff      ff
1       aff      fff      ff
2       aff      fff      92 
3       001      fff      00   

基本上我想查询数据库并查看特定查询是否匹配,例如 a00-111-12

任何地方都有 f < / b>(这都是十六进制)我想说有一个匹配。

所以我取值 a00-111-12 它应该与行0和1匹配但不匹配2和3,因为在行0中,所有 f < / b>出现,因此与它们的值和将导致相同的值。但是,AND-ing不起作用,因为如果使用第2行测试,Mask3列值92和12与12结果会产生12,但我不希望该行匹配。

我觉得这个问题很难解决,用一些MySQL查询可能无法实现,但我想避免将整个表导入PHP,然后从那里找到正确的行。

查询的想法是:     


    SELECT * FROM TABLE WHERE Mask1 = a00 AND Mask2 = 111 AND ...
    
但是,需要对Mask1,2,3或发送到查询的值进行某些操作。

最终目标是从匹配的行中获取类型。如果您需要更多信息,请询问。

2 个答案:

答案 0 :(得分:0)

创建子掩码表以使您的工作更轻松,添加一行

 z1 :  z2  : z3
0xf : 0xf0 : 0xf00

然后使用以下查询

   Select 
           t.*
   from Table t 
   inner join submasks s
     on (
         ((t.Mask1 & s.z1) = s.z1 || (t.Mask1 & s.z1) = (a00 & s.z1)) &&
         ((t.Mask1 & s.z2) = s.z2 || (t.Mask1 & s.z2) = (a00 & s.z2)) &&
         ((t.Mask1 & s.z2) = s.z2 || (t.Mask1 & s.z2) = (a00 & s.z2)) &&
         ((t.Mask2 & s.z1) = s.z1 || (t.Mask2 & s.z1) = (111 & s.z1)) &&
         ((t.Mask2 & s.z2) = s.z2 || (t.Mask2 & s.z2) = (111 & s.z2)) &&
         ((t.Mask2 & s.z2) = s.z2 || (t.Mask2 & s.z2) = (111 & s.z2)) &&
         ((t.Mask3 & s.z1) = s.z1 || (t.Mask3 & s.z1) = (12 & s.z1)) &&
         ((t.Mask3 & s.z2) = s.z2 || (t.Mask3 & s.z2) = (12 & s.z2))
   )

这种方法的工作方式是比较各个十六进制数字,方法是使用z1z2z2进行按位AND,分别得到3位数字。

所以

  • <any value> & z1将除最后一个以外的所有十六进制数字设置为0,即0x123变为0x003
  • <any value> & z2将除最后一个之外的所有十六进制数字设置为0,即0x123变为0x020
  • <any value> & z3将除最后一个之外的所有十六进制数字设置为0,即0x123变为0x100

使用此过滤器可以将每个数字的测试构建为

((mask & filter) = filter)          // is the digit f
||                                  // OR
((mask & filter) = (test & filter)) // is the digit the same.

z1z2z3(即0x00f0x0f00xf00)中的每一项重复测试结果使用和条件,您可以检查掩码的所有3个十六进制数字是f还是完全是测试值。

然后对Mask2和Mask3重复这一过程(但只有z1,z2,因为Mask3是2位数)。

通过对子掩码表使用内连接,结果将只包括掩码条件为真的表中的值。

更新 - 您可能希望执行select distinct而不只是select,就像两个掩码与表格中的一行匹配一样,然后会返回2个结果。

答案 1 :(得分:0)

不知道我是否已经足够好地解释了我的问题,但我最终得出结论:这是最好的:

val1 = 0xa00
val2 = 0x111
val3 = 0x12

SELECT * FROM TABLE WHERE 
((Mask1 | val1)=val1 OR (Mask1 | val1)=0xfff) AND
((Mask1 | val2)=val2 OR (Mask1 | val2)=0xfff) AND
((Mask1 | val3)=val3 OR (Mask1 | val2)=0xfff);

唯一的问题是val1=a00Mask1=aff不匹配,尽管我希望如此。还在努力......