我试图对我的查询使用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 ..
...
现在,来自id = 3
的{{1}}为'66',这意味着它有table1
和64 or movies
但
他也没有2 or art
两次和32 or actor
??
2 or art
和64 or movies
。
但有时我希望2 or art
中的三个id's
属于来自table2
的{{1}}
任何想法?
由于
答案 0 :(得分:11)
使用按位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
到MySQL,它可以进一步缩写为:
SELECT *
FROM table
WHERE id & 66
答案 1 :(得分:4)
select * from table2 where id & 66
答案 2 :(得分:4)
虽然已经回答了关于如何在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中的相关行。
答案 3 :(得分:0)
在回答了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