繁体   English   中英

如何在PHP中使用MySQL按位运算?

[英]how to use MySQL bitwise operations in php?

我试图使用MySQL按位运算我的查询,我有这个例子:

table1
id      ptid
1       3
2       20
3       66
4       6

table2
id     types
1      music
2      art
4      pictures
8      video
16     art2
32     actor
64     movies
128    ..
...

现在,来自table1id = 3是'66',女巫意味着它有64 or movies2 or art

不是他也有32 or actor两次和2 or art

希望你看到我的困惑在哪里。 我如何控制我想要的结果。 在这种情况下,我想要64 or movies2 or art

但有时我希望table2三个id's属于table1id

有任何想法吗?

谢谢

使用按位OR

以下查询返回66中表2中的所有项:

SELECT *
FROM table2
WHERE id | 66 = 66

但是32 + 32 = 64?

虽然32 + 32 = 64,但它不会影响我们。

这是二进制的64:

01000000

这是二进制的32:

00100000

这里是二进制的2:

00000010

这是我们在这种情况下使用的1的位置,而不是值。 不会有两件事。 每个标志都打开或关闭。

这是二进制的66。 请注意,64和2已打开,而不是32:

01000010

使用按位AND而不是OR

编写查询的另一种方法是使用按位AND,如下所示:

SELECT *
FROM table
WHERE id & 66 <> 0

由于0 = false ,因此可以进一步缩写为:

SELECT *
FROM table
WHERE id & 66
select * from table2 where id & 66

尽管已经回答了关于如何在MySQL中执行按位运算的问题,但是关于为什么这可能不是最佳数据模型的评论中的子问题仍然很突出。

在给出的示例中,有两个表; 一个带有位掩码,另一个带有每个位代表的分解。 这意味着,在某些时候,必须将两个表连接在一起以返回/显示各个位的含义。

这种联接可以是明确的,例如

SELECT * 
FROM Table1 
    INNER JOIN TABLE2 
        ON table1.ptid  & table2.id <> 0

或隐式,您可以从table1选择数据到您的应用程序,然后再次调用查找位掩码值,例如

SELECT * 
FROM table2
WHERE id & $id <> 0 

这些选项都不是想法,因为它们不是“sargable”,即数据库无法构建Search ARGument。 因此,您无法使用索引优化查询。 查询的成本超出了无法利用索引的范围,因为对于表中的每一行,DB必须计算和计算表达式。 这非常快速地变成了内存,CPU和I / O密集型,如果不从根本上改变表结构就无法进行优化。

除了完全无法优化查询之外,读取数据,报告数据也很尴尬,并且您还可能遇到限制添加更多位(8位列中的64个值现在可能没问题但不一定总是他们也使系统难以理解,我认为这种设计违反了第一种正常形式。

尽管在数据库中使用位掩码通常是设计糟糕的标志,但有时候使用它们也很好。 实现多对多关系真的不是那个时代之一。

实现此类关系的典型方法如下所示:

table1 
Id        Val1         Val2
---------------------------
1         ABC          DEF
2         ABC          DEF
3         ABC          DEF
4         ABC          DEF
5         ABC          DEF
6         ABC          DEF

table2
id     types
-------------
1      music
2      art
3      pictures
4      video
5      art2
6      actor
7      movies

table1-table2-relationshitp
table1ID    Table2ID
---------------------
1           1
1           2 
2           3
2           5
3           2
3           7
...

你会这样查询数据

SELECT table1.*, table2.types
FROM table1 
     INNER JOIN table1-table2-relationship 
          ON table1.id = table1-table2-relationship.table1id
     INNER JOIN table2 
          ON table1-table2-relationship.table2.id = table2.id

根据这些表的访问模式,您通常会将关系表上的两个列都作为复合索引编制索引(我通常将它们视为复合主键。)此索引将允许数据库快速查找到的相关行。关系表然后查找table2中的相关行。

在回答了Marcus Adams的回答之后,我想我会提供另一个例子来帮助我理解如何使用按位运算来连接两个表。

考虑下面的样本数据,它定义了一个元音表,以及一个单词表,其中一个值表示该单词中存在的元音。

# Create sample tables.
drop temporary table if exists Vowels;
create temporary table Vowels 
(
    Id int, 
    Letter varchar(1)
);
drop temporary table if exists Words;
create temporary table Words
(
    Word varchar(20),
    Vowels int
);

# Insert sample data.
insert into Vowels
    select 1,   'a' union all
    select 2,   'e' union all
    select 4,   'i' union all
    select 8,   'o' union all
    select 16,  'u';
insert into Words 
    select 'foo',           8  union all 
    select 'hello',         10 union all
    select 'language',      19 union all
    select 'programming',   13 union all
    select 'computer',      26;      

我们现在可以将Vowel表连接到Word表,如下所示:

# List every word with its vowels.
select Word, Vowels, Letter, Id as 'Vowel Id'
from (
    select *
    from Words
) w
join Vowels v
where v.Id | w.Vowels = w.Vowels
order by Word, Letter;

当然,我们可以将任何条件应用于内部查询。

# List the letters for just the words with a length < 6
select Letter
from (
    select *
    from Words
    where length(Word) < 6
) w
join Vowels v
where v.Id | w.Vowels = w.Vowels
order by Word, Letter

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM