zoukankan      html  css  js  c++  java
  • SQL建模错误--逗号分隔值

    最近帮一个客户分析SQL语句的问题,大致经过如下

    场景:

      委托方有一个用于追踪他们产品的系统,每个产品都会卖给许多客户;但是客户又被从业务上分成两类,一类是带有合作伙伴性质的,这个

      合作伙伴通常会给予产品一些建设性的意见,和问题反馈;还有一类就是普通客户了。

    程序的第一个版本

    create table customer(
        id int not null auto_increment, -- 客户id
        name varchar(16),-- 客户名
        constraint pk__customer__id primary key(id));
    -- customer表用于记录客户的信息
    
    create table product(
        id int not null auto_increment, -- 产品id
        name varchar(32), -- 产品名
        partner int not null, -- 合作伙伴id 
        constraint fk__product__partner foreign key(id) references customer(id),
        constraint pk__product__id primary key(id));
    -- product表用于记录产品信息
    
    -- 比如说目前的客户有google,facebook,apple; 它们都用了atlas-1.23这个产品;但只有google作为atlas-1.23的合作伙伴
    insert into customer(name) values('google'),('facebook'),('apple');
    
    -- 查询customer表中的信息
    select * from customer;
    +----+----------+
    | id | name     |
    +----+----------+
    |  1 | google   |
    |  2 | facebook |
    |  3 | apple    |
    +----+----------+
    
    -- google 作为atlas-1.23这个产品的合作伙伴
    insert into product(name,partner) values('atlas-1.23',1);

    这个数据库的逻辑结构有一个问题,就是一个产品是有一个合作伙伴,为了迎合业务数据库的逻辑结构有了第二个版本

    程序的第二版

    create table customer(
        id int not null auto_increment, -- 客户id
        name varchar(16),-- 客户名
        constraint pk__customer__id primary key(id));
    -- customer表用于记录客户的信息
    
    create table product(
        id int not null auto_increment, -- 产品id
        name varchar(32), -- 产品名
        partner varchar(32), -- 合作伙伴名
        constraint pk__product__id primary key(id));
    -- product表用于记录产品信息
    
    -- 比如说目前的客户有google,facebook,apple; 它们都用了atlas-1.23这个产品;但只有google作为atlas-1.23的合作伙伴
    insert into customer(name) values('google'),('facebook'),('apple');
    
    -- 查询customer表中的信息
    select * from customer;
    +----+----------+
    | id | name     |
    +----+----------+
    |  1 | google   |
    |  2 | facebook |
    |  3 | apple    |
    +----+----------+
    
    -- google 作为atlas-1.23这个产品的合作伙伴
    insert into product(name,partner) values('atlas-1.23','google');
    
    -- 
    select * from product;
    +----+------------+---------+
    | id | name       | partner |
    +----+------------+---------+
    |  1 | atlas-1.23 | google  |
    +----+------------+---------+
    
    -- 把facebook也设置成atlas-1.23这个产品的合作伙伴
    update product set partner=concat(partner,',','facebook') where name='atlas-1.23';
    
    -- 查看atlas-1.23中是否包涵有google & facebook
    select * from product;
    +----+------------+-----------------+
    | id | name       | partner         |
    +----+------------+-----------------+
    |  1 | atlas-1.23 | google,facebook |
    +----+------------+-----------------+

    这个看是完成了业务上的要求,但是它招来了魔鬼

    select * from product;
    +----+------------+------------------------+
    | id | name       | partner                |
    +----+------------+------------------------+
    |  1 | atlas-1.23 | google,facebook        |
    |  2 | alano      | facebook,google,Google |
    +----+------------+------------------------+

      1、这会引起常用的b-tree索引,hash索引失去作用如:select name from product where partner like '%google%';

      2、数据的准确性有问题,因为你无法保证不出现google,Google这样的值存在;

      3、可扩展性并不强,也就是说如果合作伙伴足够多那么它就会超过varchar(32)的范围;

    那么这个要怎么改进呢?

    程序的第三个版本就出来了

    create table customer(
        id int not null auto_increment, -- 客户id
        name varchar(16),-- 客户名
        constraint pk__customer__id primary key(id));
    -- customer表用于记录客户的信息
    
    
    create table product(
        id int not null auto_increment, -- 产品id
        name varchar(32), -- 产品名
        constraint pk__product__id primary key(id));
    -- product表用于记录产品信息
    
    create table product_partner(
        id int not null auto_increment primary key,
        product_id int not null,
        customer_id int not null,
        constraint fk__product_id foreign key(id) references product(id),
        constraint fk__customer_id foreign key(id) references customer(id));
    -- product_partner 表用于保存一个product对应的partner。
    
    insert into customer(name) values('googl');
    insert into product(name) values('atlas-1.23');
    
    select * from product;
    +----+------------+
    | id | name       |
    +----+------------+
    |  1 | atlas-1.23 |
    +----+------------+
    select * from customer;
    +----+-------+
    | id | name  |
    +----+-------+
    |  1 | googl |
    +----+-------+
    
    insert into product_partner(product_id,customer_id) values(1,1);
    
    select * from product_partner;
    +----+------------+-------------+
    | id | product_id | customer_id |
    +----+------------+-------------+
    |  1 |          1 |           1 |
    +----+------------+-------------+
  • 相关阅读:
    css之布局
    css之浮动
    白扯之聊聊我们的情怀
    Vue之指令
    Vue之vue.js声明式渲染
    AJAX经常遇到的那些问题
    HTTP之cookie技术
    正则表达式资料
    require.js资料
    AMD 和 CMD 的区别
  • 原文地址:https://www.cnblogs.com/JiangLe/p/6178673.html
Copyright © 2011-2022 走看看