我必须在发布表中执行select查询,其中设置了整数的特定位。 整数表示位掩码中的一组类别: E.g。
1 => health
2 => marketing
3 => personal
4 => music
5 => video
6 => design
7 => fashion
8 => ......
数据示例:
id | categories | title
1 | 11 | bla bla
2 | 48 | blabla, too
我需要一个mysql查询来选择标记为特定类别的帖子。 让我们说“所有视频帖子” 这意味着我需要一个贴子结果集,其中设置了catgories列的第5位(例如16,17,48 ....)
SELECT * FROM postings WHERE ....????
有什么想法吗?
答案 0 :(得分:11)
您可以像这样使用bitwise运算符。对于视频(第5位):
WHERE categories & 16 = 16
为每个位使用以下值替换值16
:
1 = 1
2 = 2
3 = 4
4 = 8
5 = 16
6 = 32
7 = 64
8 = 128
这从最低位到最高位,这与大多数程序员的想法相反。它们也从零开始。
答案 1 :(得分:3)
怎么样
SELECT * FROM postings WHERE (categories & 16) > 0; -- 16 is 5th bit over
这个问题的一个问题是你可能不会遇到索引,因此如果数据量很大,你可能会遇到性能问题。
某些数据库(例如PostgreSQL)允许您在这样的表达式上定义索引。我不确定mySQL是否具有此功能。如果这很重要,您可能需要考虑将这些分解为单独的布尔列或新表。
答案 2 :(得分:-2)
SQL(不仅仅是mySQL)不适合按位操作。如果你按位进行AND,你将强制进行表扫描,因为SQL将无法使用任何索引,并且必须一次检查每一行。
如果你创建一个单独的“Categories”表和一个正确索引的多对多PostingCategories表来连接这两个表会更好。
<强>更新强>
对于坚持认为位图字段不是问题的人来说,检查Joe Celko的BIT of a Problem是有帮助的。在文章的底部是由位图引起的严重问题列表。
关于全面陈述不正确的评论,注意#10 - 它打破了1NF所以是的,位图字段是坏的:
我还要补充一下,NULL怎么样? 缺少标志怎么样?如果某事既不是真的也不是假的呢?
最后,关于压缩声明,大多数数据库在内部将位字段打包为字节和整数。在这种情况下,位图字段不提供任何类型的压缩。其他数据库(例如PostgreSQL)实际上有一个布尔类型,可以是true / false / unknown。它可能需要1个字节,但不大量存储,如果表格太大,则可以使用透明压缩。
事实上,如果一个表变大,位图字段问题会变得更加严重。如果您被迫使用表扫描,或者如果您失去分组能力,则在GB表中保存几MB是没有益处的