如何在php中使用MySQL逐位操作?

如何在php中使用MySQL逐位操作?,php,mysql,bitwise-operators,Php,Mysql,Bitwise Operators,我尝试在查询中使用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 .. ... 现在,来自表1的id=3是'66',这意味着它有64部电影和2部或

我尝试在查询中使用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    ..
...
现在,来自
表1
id=3
是'66',这意味着它有
64部电影和
2部或艺术片

但是

他不是也有过两次
32或actor
2或art

希望你看到我的困惑所在。我如何控制我想要的结果。在这种情况下,我想要
64或电影
2或艺术

但有时我希望
table2
中的三个
id
属于
table1中的
id

有什么想法吗


感谢您使用按位或

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

SELECT *
FROM table2
WHERE id | 66 = 66
但是32+32=64?

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

这是64位二进制:

01000000
00100000
00000010
这是32个二进制文件:

01000000
00100000
00000010
这是二进制的2:

01000000
00100000
00000010
在本例中,我们使用的是1的位置,而不是值。什么都不会有。每个标志要么打开,要么关闭

这是二进制的66。请注意,64和2处于启用状态,而不是32:

01000010
使用按位AND而不是OR

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

SELECT *
FROM table
WHERE id & 66 <> 0
SELECT *
FROM table
WHERE id & 66
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
...

虽然关于如何在MySQL中执行逐位操作的问题已经得到了回答,但评论中关于为什么这可能不是最佳数据模型的子问题仍然没有解决

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

此联接可以是显式的,例如

SELECT * 
FROM Table1 
    INNER JOIN TABLE2 
        ON table1.ptid  & table2.id <> 0
这两个选项都不是想法,因为它们不是“可搜索的”,也就是说,数据库不能构造搜索参数。因此,您无法使用索引优化查询。查询的成本超出了无法利用索引的范围,因为对于表中的每一行,DB都必须计算和计算一个表达式。这将非常快地占用大量内存、CPU和I/O,如果不从根本上改变表结构,就无法对其进行优化

除了完全无法优化查询之外,读取数据、报告数据也可能会很麻烦,而且添加更多位也可能会遇到限制(8位列中的64个值现在可能很好,但不一定总是这样。它们也使系统难以理解,我认为这种设计违反了第一范式

虽然在数据库中使用位掩码通常是设计不好的标志,但有时使用位掩码是可以的。实现多对多关系实际上不属于这种情况

实现这种关系的典型方法如下所示:

SELECT *
FROM table
WHERE id & 66 <> 0
SELECT *
FROM table
WHERE id & 66
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

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

在研究了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;      
我们现在可以将
元音
表连接到
单词
表,如下所示:

# 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
#仅列出长度小于6的单词的字母
选择字母
从(
挑选*
言辞
其中长度(字)<6
)w
连接元音v
其中v.Id | w.元音=w.元音
按字、字母顺序

ew!这是一个糟糕的数据模型。出于好奇,你为什么不使用一个单独跟踪id->ptid关系的表?你想在MySQL中使用逐位操作来连接两个表???我的眼睛!护目镜什么都不做!但说真的,正如@jprofitt所说,为什么不使用更标准的多个关系模型呢?这是MySQL pag爱国者问得好。我贴了一个答案,因为它需要比这里更多的空间。