引言
大家应该遇到过这种场景,某个表中的一个字段有多种状态且多种状态可以并存,读到这里相信优秀的你觉得这个场景很熟悉或者有点陌生,不着急慢慢看;实际的例子有很多:用户的兴趣标签、电商中店铺的配送模式和某个店铺支持的支付方式等。
标志位法
概述
这种方法我实际的项目中就有用到过,我就举个例子:用户的兴趣标签
用户的兴趣标签列表如下:
- 篮球
- 动漫
- 小说
- 电影
- 健身
-
写博客
(嘿嘿嘿)
定义一个长度为6的字符串,字符串的每一位代表一种兴趣,0表示 没有这个兴趣,1表示有这个兴趣,当然顺序是固定好的,不能变。
示例
顺序默认按照上面列表的顺序
- 100001
篮球和写博客
- 101010
篮球、小说和健身
操作
- 设置兴趣
可以和前端约定好,篮球的下标是几,动漫的下标是几,约定好由前端传过来感兴趣的下标(多个由逗号分隔)就行。下标就按照上面列表的顺序,从0开始到写博客
为5,则前端回传过来:
前端的格式 | 后端的格式 | 描述 |
---|---|---|
1,3,4 | 010110 | 动漫、电影和健身 |
3,5 | 000101 | 电影和写博客 |
1,2,5 | 011001 | 动漫、小说和写博客 |
- 查询兴趣
标志位的设计给查询带来了困难,由于兴趣
标签以varchar 的形式存储在数据库中所以我们需要通过LIKE
方式去查询:
要查询感兴趣的标签 | sql |
---|---|
健身和写博客 | select * from xx where interest like '____11' |
电影和写博客 | select * from xxx where interest like '___1_1' |
动漫、小说和写博客 | select * from xxx where interest like '_11__1' |
备注
:_ 占位符 占一位。大家有啥好的查询方式也可以发出来。
二进制法
这种方法实际项目中我没有用过,这是我自己查点资料学习的,因为我觉得使用标志位法查询不好查。使用二进制法就需要涉及到一些位运算,注意:mysql 也支持位运算。
关于兴趣以下定义:
BASKETBALL 1
ANIME 2
NOVEL 4
MOVIE 8
FITNESS 16
WRITE_BLOG 32
组合
BASKETBALL 和 ANIME 等价于 1|2=3 存到数据库里就是数字3
MOVIE 和 FITNESS 等价于8|16=24 存到数据库里就是数字24
WRITE_BLOG 、FITNESS 和NOVEL 等价于32|16|4=52 存到数据库里就是数字52
此时数据库里只要存数字就行。
👆看明白了吧,现在大家比较纠结的应该是怎么查? 查询就用到& 运算了
- 查询兴趣
要查询感兴趣的标签 | sql |
---|---|
健身和写博客 | select * from xx where interest &48 |
电影和写博客 | select * from xxx where interest &40 |
动漫、小说和写博客 | select * from xxx where interest &38 |
比较
指标 | 标志位法 | 二进制法 |
---|---|---|
可读性 | 较差 | 差 |
是否可使用索引 | 某些查询可以 | 完全不可以 |
sql 组装复杂度 | 差 | 较好 |
后记
大家有没有更好的方法呢,欢迎大家讨论交流。大家感觉有没有学到东西呢?我建议看完一篇文章之后可以问问自己有没有学了什么,这样才会促进自己的成长。
网友评论