最近帮一个客户分析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 |
+----+------------+-------------+

SQL建模错误--逗号分隔值的更多相关文章

  1. sql server中单引号拼接字符串(书写错误会出现错误"浮点值 XXXX 超出了计算机表示范围(8 个字节)。“XX”附近有语法错误。")

    " ' "(单引号)的运用:在sql server中,两个" ' "(单引号)在拼接字符串的情况下运用,就是表示拼接上了一个" ' "单引号 ...

  2. SQL Server 错误日志过滤(ERRORLOG)

    一.背景 有一天我发现SQL Server服务器的错误日志中包括非常多关于sa用户的登陆错误信息:“Login failed for user 'sa'. 原因: 评估密码时出错.[客户端: XX.X ...

  3. MS SQL 监控错误日志的告警信息

    SQL Server的错误消息(Error Message)按照消息的严重级别一共划分25个等级,级别越高,表示严重性也越高.但是如果你统计sys.messages,你会发现,实际上只有16(SQL ...

  4. SQL Server自动化运维系列——监控磁盘剩余空间及SQL Server错误日志(Power Shell)

    需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 在所有的自检流程中最基础的一个就是磁盘剩余空间检测. ...

  5. SQL Server代理(5/12):理解SQL代理错误日志

    SQL Server代理是所有实时数据库的核心.代理有很多不明显的用法,因此系统的知识,对于开发人员还是DBA都是有用的.这系列文章会通俗介绍它的很多用法. 如我们在这个系列的前几篇文章所见,SQL ...

  6. SQL Server自动化运维系列 - 监控磁盘剩余空间及SQL Server错误日志(Power Shell)

    需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 在所有的自检流程中最基础的一个就是磁盘剩余空间检测. ...

  7. 获取动态SQL查询语句返回值(sp_executesql)

    在写存储过程时经常会遇到需要拼接SQL语句的情况,一般情况下仅仅是为了执行拼接后的语句使用exec(@sql)即可. 而今天的一个存储过程却需要获取动态SQL的查询结果. 需求描述:在某表中根据Id值 ...

  8. sql server 错误日志errorlog

    一 .概述 SQL Server 将某些系统事件和用户定义事件记录到 SQL Server 错误日志和 Microsoft Windows 应用程序日志中. 这两种日志都会自动给所有记录事件加上时间戳 ...

  9. Oracle 在函数或存储过程中执行sql查询字符串并将结果值赋值给变量

    请看黄色部分 --区县指标 THEN TVALUE_SQL := 'SELECT TO_CHAR(' || CUR_ROW.MAIN_FIELD || ') FROM ' || CUR_ROW.END ...

随机推荐

  1. poj 3232 Accelerator

    http://poj.org/problem?id=3232 题意:有一个含有n辆车的车队,当前距离终点的距离已知,有m个加速器,每个加速器在一个时刻只能给一辆车用,一旦使用就会使得其速度由1变成k, ...

  2. Qt on Android

    Qt on Android Episode 7(翻译) http://blog.csdn.net/foruok/article/details/46323129 Android基础整理之四大组件Act ...

  3. ~/.bashrc的常用alias设置

    centos6.5系统中,alias定义在/etc/bashrc,分别写在/etc/profile.d/*.sh中,可以在此目录添加my.sh, alias attrib='chmod'alias c ...

  4. BZOJ3391: [Usaco2004 Dec]Tree Cutting网络破坏

    3391: [Usaco2004 Dec]Tree Cutting网络破坏 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 47  Solved: 37[ ...

  5. 【转】文件同步软件FreeFileSync

    原文网址:http://imcn.me/html/y2012/9855.html FreeFileSync 是一款开源的文件夹比较和同步工具,可用于 Win 和 Lin 平台,最近发布了 5.0 版本 ...

  6. VS013的单元测试去哪里了

    需要安装这个插件 http://visualstudiogallery.msdn.microsoft.com/45208924-e7b0-45df-8cff-165b505a38d7

  7. linux下常用FTP命令

    linux下常用FTP命令 1. 连接ftp服务器 1. 连接ftp服务器格式:ftp [hostname| ip-address]a)在linux命令行下输入: ftp 192.168.1.1b)服 ...

  8. 从此走上一条iOS程序猿不归路。。。

    新的城市,新的生活!前不久刚刚结束了苦逼的面试找工作之旅,期间也小有收货,如今正处年底工作闲暇之余,将前一阵子陆陆续续的总结整理了一下,本人菜鸟程序猿一只,水平有限,本文总结的知识不算深入,比较浅显, ...

  9. [深入React] 6.组件

    组件是react的大杀器,超出其他框架几百里 react 组件和dom一样也是树状结构,只能由上而下传递变量(或者调用),不可以兄弟间或者更远的发生关系,为的就是简单,而且工作的很好. 每个组件有自己 ...

  10. wpf下拉框不能多选的原因

    <dxe:ComboBoxEdit Margin="0"  Height="25" Width="65" VerticalAlignm ...