位运算-设计数据库表的多选状态字段

案例:存储用户的兴趣爱好,多选。
一个人肯定有打篮球,看书等多个爱好。

设计方式一:多对多存储

表: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):代表足球;第三位

30001+0010=0011):代表篮球、看书;
50001+0100=0101):代表篮球、足球;
60010+0100=0110):表示看书、足球;
70001+0010+0100=0111):表示篮球、看书、足球;
本作品采用《CC 协议》,转载必须注明作者和本文链接
附言 1  ·  1年前

方法三缺点:
位运算不走索引,暂时没什么好方法解决

不合适类似角色与权限的这种多选组合,如数据库字段hobby(兴趣)(int)类型,最多只能有八个选项

数据库直接看的话不直观,个人觉得如果数据需要直接在数据库操作查看,那这系统有何意义?

附言 2  ·  1年前

抱歉,关于八个选项,搞go魔怔了,下意识把int当成uint8了

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 13

如果有超过 64 个爱好,咋办呢

1年前 评论
OnlyRed (楼主) 1年前
wxf666 (作者) 1年前
OnlyRed (楼主) 1年前
wxf666 (作者) 1年前

我有一种很新颖的方式存储方式,就是用mysql的bite类型存储,比如说我有3种类型:篮球、足球,乒乓球,那我存储的类型是bite(3),如果不勾选的话值是 000, 如果选择的是篮球则是100, 其他的同理可得。这种方法就简便很多。

1年前 评论
wxf666 1年前

恰好这两天整理了一个位运算编码多状态的通用类 - BitEncoder

1年前 评论

MYSQL位运算查询包含某个状态的记录,不走索引,每次都全表查询 这个大佬有好的解决方法吗

1年前 评论
guanguans 1年前
whatsdream (作者) 1年前
OnlyRed (楼主) 1年前
wxf666 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!