一、引言

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

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

这种用多个字段满足多种状态方案的确满足了项目需求,但是存在两个缺点,

(1)增加了数据字段冗余和增加存储空间;

(2)可拓展性差,比如增加一种钻石卡,只能在数据库中,增加一个字段,这样多项目改动是较大的。

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

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

(1)字符串表达

​ 这种方法就是将多个状态标识字段通过字符串拼接表示成一个字段。如:

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

​ 优点:

(1)消除冗余状态字段;

(2)增加可拓展性,增加新的会员卡类别时,不需增加新的字段,增加一种新字符就行。

​ 缺点:

(1)查询效率低,想查询支持银卡的商家,首先遍历整个数据库,然后对状态字符串进行分隔,最后才能查询;

查询用FIND_IN_SET(str,strlist)函数;

(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)表示,2的n次方

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

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

​ 优点:

(1)无字段冗余,节省存储空间;

(2)可拓展性强;

(3)查询效率高。

​ 缺点:

​ 如果种类过多,2的n次方的数值也会越大,根本就无法存储和运算。

(3)“位”表示–优化

这个方案进行一些改进:

  1. 每一个值都用一个二进制的字符串表示 ,如1,10,100,1000,这里它们都是字符串。

  2. 如拥有以上两个,比如权限值为1010,这里需要自己写一个函数来进行字符串的拼接和替换。

  3. 查询的时候,需要自己写一个类似的bitand的函数(Oracle的),处理字符串的匹配。

    bitnd函数的语法为以下:

    bitand(a , b)

    若 a= 2; b=3

    a 的 二进制为 0100

    b 的 二进制为 0110

    若相对应的位置都为1,则为 1,否则为0

    所以 bitand(2 , 3) = 0100 = 2

    例如,A表存放3个通知类型,其值分别是2的0次幂、1次幂、2次幂,

    id  name    value
    1   短信      1
    2   邮件      2
    3   即时通讯   4
    

    B表存放功能对应的通知类型的值之和,

    id   func_name   code
    1    会议管理      3  -- 通知方式:短信、邮件
    2    公告通知      7  -- 通知方式:短信、邮件、即时通讯
    3    信息报送      2  -- 通知方式:邮件
    

    查询:

    • 查询通知方式为短信、邮件的(两者相加是3)

      select b.* from B b where bitand(to_number(b.code), 3)>0 ;
      
    • 查询B表中”会议管理“的通知类型:(通过B表中code=3查询出所含的类型)

      select a.name  from A a where bitand(to_number(a.value), 3) = to_number(a.value);
      

      分析:

      ​ 3: 0011

      ​ 1: 0001 结果1 1=1

      ​ 2: 0010 结果2 2=2

      ​ 4: 1000 结果0 0!= 4

      所以,查询的是短信、和邮件。

​ 优点:解决(2)用int类型存取的值过大的问题。

​ 缺点:bitand函数是Oracle中的,其他数据库需要自定义。

(4)关系表(或:数据字典)

​ 如果种类过多,就得创建种类表保存信息,关系表保存主表和次表的关系。

例如,教师表:

-- teacher
id  name
1   张三
2   李四

​ 科目表:

-- subject
id  name
1   语文
2   数学
3   体育

​ 关系表:(众所周知,数学是体育老师教的哈哈)

-- teacher_subject_rel
id  teacher_id  subject_id
1       1           2
2       1           3
3       2           1

缺点:新增了一张表,就需要多关联一张中间表,可能代码量也会增加。

如有不恰当之处,望诸君即时指出,谢谢。
摘抄:
https://chunsoft.blog.csdn.net/article/details/82356664

数据库设计之多选状态设计相关推荐

  1. mysql 多选数据库设计_数据库设计:多选查询与匹配

    数据库设计:多选查询与匹配 在权限管理的数据库设计中,可能会遇到 这样的问题: 查询具有某些权限的用户,权限是多选的,用户可能具有一个或多个选择的权限. 这个问题的解决方案是有多种,比较常见的有. 1 ...

  2. 经营分析、决策系统数据库设计 - 实时圈选、透视、估算

    点击有惊喜 背景 经营分析.决策支持是现代企业的一个让数据发挥有效价值的分析型系统. 在各个行业中随处可见,例如共享充电宝中,协助销售了解实时的设备租赁情况,销售业绩.在电商中,协助小二和商户发掘目标 ...

  3. React组件设计实践总结05 - 状态管理

    今天是 520,这是本系列最后一篇文章,主要涵盖 React 状态管理的相关方案. 前几篇文章在掘金首发基本石沉大海, 没什么阅读量. 可能是文章篇幅太长了?掘金值太低了? 还是错别字太多了? 后面静 ...

  4. Objective-C使用位运算设计可复选的枚举

    2019独角兽企业重金招聘Python工程师标准>>> Objective-C使用位运算设计可复选的枚举 使用位运算设计可复选的枚举 一.枚举使用的一个小例子 在软件开发中,枚举是我 ...

  5. SaltStack的salt-ssh使用及LAMP状态设计部署

    SaltStack的salt-ssh使用及LAMP状态设计部署 1.salt-ssh的使用 官方文档:https://docs.saltstack.com/en/2016.11/topics/ssh/ ...

  6. android recycleview长按多选_UI设计中Android和IOS设计差异总结

    由于设计师.产品经理使用的移动设备大部分是iPhone,所以在做设计时,容易忽略Android和iOS的差异,按照iOS的规范进行设计,两端只做一套. 只做一套的会存在两个问题: 1.安卓用户的使用习 ...

  7. vue外卖十九:商家详情-底部购物车组件,购物车相关vuex状态设计、相关计算、清空购物车+滚动购物车

    一.购物车基础 1)购物车状态设计cartFoods+mutation store/state.js // 所有要管理的状态数据:从页面需求分析出来,最好和api/index.js里的命名相同 exp ...

  8. 数据库设计-多级栏目(标题)分类设计

    数据库设计-多级栏目(标题)分类设计 文章目录 数据库设计-多级栏目(标题)分类设计 栏目表 内容表 栏目表 id cid cname 主键 栏目级别id 栏目名 栏目cid:一级栏目,二级栏目,三级 ...

  9. 基于TCGA及SEER等癌症公共数据库的深度挖掘和科研设计会议

    基于TCGA及SEER等癌症公共数据库的深度挖掘和科研设计 培训通知 各事业单位: 身处大数据时代,对于从事肿瘤研究的临床医生或基础科研人员,有没有一种可以既不做实验又不查病史,直接调用公共数据撰写发 ...

最新文章

  1. 全文翻译(一):TVM: An Automated End-to-End Optimizing Compiler for Deep Learning
  2. go 的des加解密
  3. 博士申请 | 美国罗格斯大学王灏助理教授招收机器学习方向博士生
  4. 一个命名管道可以被多个客户端访问吗_Redis 的事务机制和管道技术Pipelining
  5. URAL 1036 Lucky Tickets
  6. linux查找postgre进程,postgresql数据库某一个进程占用大量CPU,问题排查详解
  7. 电脑开机提示EFI Netword 0 for ipv4 boot failed的原因及解决方法
  8. 利用Auto Deploy 部署ESXi 5
  9. SQL那些事儿(十四)--C#调用oracle存储过程(查询非查询and有参无参)深度好文
  10. Apache Kylin在美团数十亿数据OLAP场景下的实践
  11. python编辑数学函数图形_Python 绘制你想要的数学函数图形
  12. mysql微信昵称特殊符号_mysql保存微信昵称特殊字符的方法
  13. bilibili、腾讯视频下载方法及过程中遇到的一些问题
  14. Android广告图片轮播控件banner
  15. html中红色星号,使用CSS中的星号(*)通配符的总结
  16. 通过微信授权接口,获取用户微信账户信息
  17. ubuntu更新源出现错误
  18. 了解更多全国各地浴室5×8装修图片
  19. enumerate() 函数的解释
  20. 完美解决eclipse中文注释错位、缩进、被放大BUG

热门文章

  1. 微信域名检测拦截及其原理
  2. 服务器拦截微信请求,分享微信域名检测,域名拦截检测接口(官方api)
  3. 网页版贪食蛇【基于HTML+CSS+JavaScript】实现
  4. linux系统4gb够用吗,专家:手机仅需要4GB运存就够用
  5. 优化Elasticsearch查询性能
  6. HDFS伪分布式环境搭建-很不错
  7. 母函数详解(转 侵删)
  8. c语言字节和字的区别,字、字节、位、字长?区别?关系?
  9. java版商城之Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入驻商城 直播带货商城 电子商务
  10. python numpy生成等差数列、等比数列