位运算-设计数据库表的多选状态字段
案例:存储用户的兴趣爱好,多选。
一个人肯定有打篮球,看书等多个爱好。
设计方式一:多对多存储
表:users
用户表、hobbys
兴趣爱好表、user_has_hobbys
用户与兴趣爱好关联表
设计方式二:一个字段,数据用逗号分割存储(此方法一点也不推荐)
字段:hobby(int)
,数据存储方式:1,2,3
。1代表篮球 2代表看书 3代表足球
设计方式三:位运算来存储
目前自己认为的最好方法
//model 里定义(hobby)字段
const HOBBY_BASKETBALL = 1 << 0;//篮球(1)
const HOBBY_READ_BOOK = 1 << 1;//看书(2)
const HOBBY_FOOTBALL = 1 << 2;//足球(4)
//数据表(users)
id(用户ID) hobby(兴趣) name(用户名)
1 1 小花
2 2 小红
3 3 小张
4 4 小军
5 5 小明
6 6 小李
7 7 小天
实操查询
# 查询兴趣爱好为看书的
SELECT id,hobby,name FROM users WHERE hobby & 2
//结果为id:2,3,6,7
# 查询兴趣爱好为篮球or看书or足球(1+2+4=7)的
SELECT id,hobby,name FROM users WHERE hobby & 7
//结果为id:1,2,3,4,5,6,7
# 查询兴趣爱好为篮球and看书and足球(1+2+4=7)的
SELECT id,hobby,name FROM users WHERE hobby & 7 = 7
//结果为id:7
#查询的时候只用把要查询的兴趣爱好相加(前端传值也是一样相加),即可,简单方法,省事,高效
看不懂位运算 可搜索看原码、反码、补码资料,以及看下面解释
//字段字段hobby(int)
1 (0001):代表篮球;第一位
2 (0010):代表看书;第二位
4 (0100):代表足球;第三位
3(0001+0010=0011):代表篮球、看书;
5(0001+0100=0101):代表篮球、足球;
6(0010+0100=0110):表示看书、足球;
7(0001+0010+0100=0111):表示篮球、看书、足球;
本作品采用《CC 协议》,转载必须注明作者和本文链接
方法三缺点:
位运算不走索引,暂时没什么好方法解决
不合适类似角色与权限的这种多选组合,如数据库字段hobby(兴趣)
(int)类型,最多只能有八个选项
数据库直接看的话不直观,个人觉得如果数据需要直接在数据库操作查看,那这系统有何意义?
抱歉,关于八个选项,搞go魔怔了,下意识把int当成uint8了
如果有超过 64 个爱好,咋办呢
我有一种很新颖的方式存储方式,就是用mysql的bite类型存储,比如说我有3种类型:篮球、足球,乒乓球,那我存储的类型是bite(3),如果不勾选的话值是 000, 如果选择的是篮球则是100, 其他的同理可得。这种方法就简便很多。
恰好这两天整理了一个位运算编码多状态的通用类 - BitEncoder。
MYSQL位运算查询包含某个状态的记录,不走索引,每次都全表查询 这个大佬有好的解决方法吗