我的数据库中有一个表,用于存储有关用户可用性的信息,其中有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的可用性并简单地映射到表单等但我已经意识到这是一个糟糕的设计,数据在错误的地方有效地强制表之间的关系在应用程序而不是数据库中处理。
我的新设计是有两张桌子:
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 :(得分:1)
根据您的评论,我认为您可以有利地使用位和按位运算符来处理数据。
如果您的查询看起来像“找到一些在这些时间段中可用的用户”或“找到一些可用于所有这些时间段的用户”,那么您可以通过按位获得-and。
在MySql中,按位运算符是经典的C运算符:response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getFilename() + "\"");
IOUtils.copy(is, response.getOutputStream());
,&
和|
。
您可以通过枚举时隙来构造位掩码:
^
然后使用mon_day = 0
mon_eve = 1
mon_late = 2
tue_day = 3
tue_eve = 4
tue_late = 5
:
构造一个位掩码,其中X是任何枚举值。按位 - 或者它们全部在一起:
(1 << 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
检查用户是否完全可用。
这里的好处是它是一个快速选择,它是紧凑的(在你的表定义中只有一行),它很小(行中只有32位),它是一个非常直接的映射到你的“直播中的类似编码“数据结构,如果你有一个。完全相同的操作可以得到完全相同的结果。
答案 1 :(得分: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
);