2017-04-20 47 views
0

我的数据库中有一张表,用于存储有21个可用性插槽的用户可用性信息:每周3天。它看起来像这样:用户可用性表的数据库设计

CREATE TABLE user_availability(
id int(11) primary key increments, 
user_id int(11),/*foreign key*/ 
day_mon tinyint(1), 
day_tues tinyint(1), 
day_wed tinyint(1), 
day_thurs tinyint(1), 
day_fri tinyint(1), 
day_sat tinyint(1), 
day_sun tinyint(1), 
eve_mon tinyint(1), 
eve_tues tinyint(1), 
eve_wed tinyint(1), 
eve_thurs tinyint(1), 
eve_fri tinyint(1), 
eve_sat tinyint(1), 
eve_sun tinyint(1), 
late_mon tinyint(1), 
late_tues tinyint(1), 
late_wed tinyint(1), 
late_thurs tinyint(1), 
late_fri tinyint(1), 
late_sat tinyint(1), 
late_sun tinyint(1) 
); 

这似乎是在第一个是超级简单拉可用性特定USER_ID和简单映射到形式等一个好主意,但我已经意识到这是一个糟糕的设计与数据在错误的地方有效地强制在应用程序中处理表之间的关系而不是在数据库中处理。

我的新设计是有2个表:

create table user_availabilty(
id int(11) primary key increments, 
user_id int(11),/*foreign key*/ 
time_slot tinyint(2)/*foreign key*/ 
); 

create table time_slots(
id tinyint(2) primary key, 
name varchar(20) 
); 

这有什么问题呢?如果有一天我的梦想成真,并且我拥有数以万计的用户,那么每个用户的表中可能会有21行可能会出现问题?

+0

“成本”将保持不变,因为这些项目的数量是固定的。那么目的是什么?这些信息的预期用途是什么?查询会是什么样子? –

+0

预期用途是将承包商与租用人匹配。 “查询会是什么样子?”好点子!我开始回答'从usr_avail中选择不同的user_id,其中time_slot = 1和time_slot = 2',我认为这并不适用于所提出的想法。嗯,这并不理想 – kemika

回答

1

根据你的评论,我认为你可以有利地使用位和位运算符为您的数据。

如果您的查询看起来像是“找到某个可在任何这些时段使用的用户”或“找到可用于所有这些时段的用户”,那么您可以通过按位与。

在MySql中,按位运算符是经典的C运算符:&,|^

可以通过列举的时隙构造位掩码:

mon_day = 0 
mon_eve = 1 
mon_late = 2 
tue_day = 3 
tue_eve = 4 
tue_late = 5 
: 

然后构建使用(1 << X)其中X是任何枚举值的位掩码。按位或将它们放在一起:

#pseudo-code 
desired_times = 0 

for timeslot in all-timeslots 
begin 
    desired_times = desired_times | (1 << timeslot) 
end 

然后将查询是一个单比特操作:

SELECT * FROM users u 
WHERE 
    (u.availability & desired_times) = desired_times 

精确匹配所需的时间(计划?),或:

SELECT * FROM users u 
WHERE 
    (u.availability & desired_times) != 0 

查看用户是否可用。

这里的好处是它是一个快速选择,它是紧凑的(表格定义中只有一行),它很小(行中只有32位),它是一个非常直接的映射到你的“活的“数据结构,如果你有的话。完全相同的操作给出了完全相同的结果。

0

我的设计是不同的。让我与你分享;

create table user_availabilty(
id int(11) primary increments, 
user_id int(11),/*foreign key*/ 
time_slot_id tinyint(2)/*foreign key*/ 
); 

create table time_slots(
time_slot_id tinyint(2) primary, 
user_id , //foreign key 
type tinyint(2), // day,eve or late 
day_name varchar(10) // days of week 
);