数据库设计——多选状态字段设计

没人对你说「不」的时候 你是长不大的。——《战争与和平》

1、引言

在做公司的算法分析相关项目时,遇到分析状态这个字段存在多种分析算法对应的状态,并且是多选的。这样讲起来有点抽象,由于项目保密问题,也不能细讲。换个通俗的例子来说明这个问题。

例如:某个商家支持多种会员卡打折,如金卡、银卡、其他卡,多选状态。通常的做法是在商家表中建立三个字段,

gold_card(tinyint类型,0,支持;1,不支持)silver_card(tinyint类型,0,支持;1,不支持)other_card(tinyint类型,0,支持;1,不支持)

这种用多个字段满足多种状态方案的确满足了项目需求,但是存在两个缺点,
(1)增加了数据字段冗余和增加存储空间;
(2)可拓展性差,比如增加一种钻石卡,只能在数据库中,增加一个字段,这样多项目改动是较大的。

基于此问题,本文探索多选字段的设计。

2、多选字段设计解决方案

2.1 字符串表达

这是我最开始的想法,这种方法就是将多个状态标识字段通过字符串拼接表示成一个字段。如:

card_status(varchar,1表示金卡;2表示银卡;3表示其他卡;)
// 字符串拼接表示多选,如1,2表示支持金卡,银卡;1,2,3表示都支持。。。

这种方法的好处是
(1)消除冗余状态字段;
(2)增加可拓展性,增加新的会员卡类别时,不需增加新的字段,增加一种新字符就行。

但是在开发时,发现查询的时候就特别麻烦,比如:我想查询支持银卡的商家,首先我们遍历整个数据库,然后对状态字符串进行分隔。最后才能查询。

同时字符串类型的字段在查询效率和存储空间上不如整型字段。

这种方法解决了设计的字段冗余和可拓展性问题,但是在查询上效率较低。

在这里,有其他更好的解决方案吗?有,二进制位来表示。

2.2 “位”表示

二进制的“位”本来就有表示状态的作用。在这里,采用不同的位表示卡支持状态,例如:

card_status(int)
1(0001):表示支持金卡;
2(0010):表示支持银卡;
4(0100):表示支持其他卡;
3(0001+0010=0011):表示支持金卡、银卡;
5(0001+0100=0101):表示支持金卡、其他卡;
7(0001+0010+0100=0111):表示支持所有卡;

如果想拓展增加一种卡,则用8(1000)表示,再增加一种则用16(10000)表示。

当想查询时,通过位的与运算即可以查询出想要的数据:

// 查询支持银卡打折的商家信息:  
select * from seller where card_status & b'0010'  
或者:  
Select * from seller where card_status & 2  

这种方式解决了前面的三个问题:
(1)无字段冗余,节省存储空间;
(2)可拓展性强;
(3)查询效率高。

©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页