如何规范化当前的数据库结构

时间:2011-12-12 13:58:38

标签: mysql normalization

使用FIND_IN_SETLIKE时,我很头疼才能获得正确的结果。

示例我的数据库中的值,如1,2,3,4,5,6,7,8

假设我有一个包含许多复选框的表单。每个复选框都带有动态值,可以由用户添加。示例值为颜色并具有green, yellow, white, black, red, pink, brown, etc...

我目前的结构tbl_colors& tbl_users

color_id  color_name
----------------------
1         yellow
2         black
3         green
.         ...
.         ...
20        pink

tbl_users

user_id  color_id
----------------------
1         1,2,3,4
2         3,4,5,6,8,9,10
3         1
.         ...
.         ...
20        1,10,20

问题

我如何规范化&重构我上面的当前数据库,让我轻松计算用户喜欢黄色,棕色等等。

5 个答案:

答案 0 :(得分:1)

你需要一个额外的链接表。

tbl_colors
----------
color_id
color_name 

tbl_users
---------
user_id
...

tbl_users_colors_link
---------------------
user_id
color_id

请注意,链接表不应包含唯一字段。也不需要主键。只有索引id字段才有意义。

答案 1 :(得分:1)

将USER放入他/她自己的表中,然后在USER_COLOUR中记录他们的偏好,例如

User ID    Colour ID
1          10
1          11
1          15
2          10
2          7

请注意重复出现的用户ID和颜色ID。这被称为多对多关系,因为1个用户可以喜欢多种颜色,并且许多用户都可以喜欢每种颜色。

答案 2 :(得分:1)

table colors
id
color_id
color_name

table users
id

table user_color( or whatever )
id
user_id
color_id

这样,每个用户选择的颜色都有一个单独的表和一个条目,而不是每个color_id行有多个数字。 然后,您可以根据查询中的color_id计算返回的行数。 多数民众赞成我将如何做到这一点。

答案 3 :(得分:1)

many-to-many relationship

tbl_user_color
id, user_id,    color_id
--------------------
1   1   1
2   1   2
3   1   3
4   1   4
5   3   1
6   20  1
7   20  10
8   20  20
...

答案 4 :(得分:1)

请看以下链接:

http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/

http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html

然后按照(省略参照完整性)的方式设计您的模式:

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varchar(32) unique not null
)
engine=innodb;

drop table if exists colours;
create table colours
(
colour_id smallint unsigned not null auto_increment primary key,
name varchar(255) unique not null,
user_counter int unsigned not null default 0
)
engine=innodb;

drop table if exists user_colours;
create table user_colours
(
user_id int unsigned not null,
colour_id smallint unsigned not null,
primary key (user_id, colour_id) -- note the clustered composite primary key
)
engine=innodb;

delimiter #

create trigger user_colours_after_ins_trig after insert on user_colours
for each row
begin
 update colours set user_counter = user_counter + 1 where colour_id = new.colour_id;
end#

delimiter ;


insert into users (username) values ('alpha'),('beta'),('delta'),('gamma');

insert into colours (name) values ('red'),('green'),('blue');

insert into user_colours (user_id, colour_id) values
(1,1),(1,3),
(2,1),(2,2),(2,3),
(4,3);

select * from users;
+---------+----------+
| user_id | username |
+---------+----------+
|       1 | alpha    |
|       2 | beta     |
|       3 | delta    |
|       4 | gamma    |
+---------+----------+
4 rows in set (0.00 sec)

select * from colours;
+-----------+-------+--------------+
| colour_id | name  | user_counter |
+-----------+-------+--------------+
|         1 | red   |            2 |
|         2 | green |            1 |
|         3 | blue  |            3 |
+-----------+-------+--------------+
3 rows in set (0.00 sec)

select * from user_colours;    
+---------+-----------+
| user_id | colour_id |
+---------+-----------+
|       1 |         1 |
|       1 |         3 |
|       2 |         1 |
|       2 |         2 |
|       2 |         3 |
|       4 |         3 |
+---------+-----------+
6 rows in set (0.00 sec)