2011-12-12 42 views
1

使用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 

问题

如何规范&重组我的C urrent数据库上面,并且容易我计算多少用户喜欢黄色,棕色等。

回答

1

您需要额外的链接表。

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

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

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

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

+0

链接表应该有一个主键 - 一个innodb集群。 –

+0

MRA没有提到数据库引擎,但我的答案也适用于InnoDB,因为InnoDB会在内部自动创建一个6字节的unqiue密钥。你不需要创建一个。 –

1

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

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

请注意重复出现的用户ID和颜色ID。这就是众所周知的多对多的关系,因为1个用户可以喜欢很多颜色,而且每种颜色都可以被很多用户喜欢。

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返回的行数。 多数民众赞成那我该怎么做。

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)