用户可用性表的数据库设计



我的数据库中有一个表,该表存储有关用户可用性的信息,其中有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)
);

这似乎是一个好主意要在应用程序而不是数据库中处理。

我的新设计是有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行的问题?

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

如果您的查询看起来像是"找到我的一些时间插槽中可用的用户"或"找到所有这些时间插槽中可用的用户",那么您可以使用位置来获得该用户 - 和。

在MySQL中,位运算符是经典C运算符:&|^

您可以通过枚举时间插槽来构造位面具:

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

然后使用 (1 << X)构建一个bitmask,其中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位(,并且它是一个非常直接的映射,用于您的" Live中的类似编码"数据结构,如果有一个。完全相同的操作给出了完全相同的结果。

我的ording是不同的。让我与您分享;

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
);

最新更新