【问题标题】:Database design for user availability table用户可用性表的数据库设计
【发布时间】:2017-04-20 01:09:08
【问题描述】:

我的数据库中有一个表,它存储有关用户可用性的信息,其中有 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 行是否会成为问题?

【问题讨论】:

  • “成本”将保持不变,因为这些项目的数量是不变的。那么目的是什么,这些信息的预期用途是什么?查询是什么样的?
  • 预期用途是将承包商与租用人匹配。 “查询会是什么样子?”好点子!我开始回复select distinct user_id from usr_avail where time_slot = 1 and time_slot=2,我认为这在提议的想法中不起作用。嗯,这并不理想

标签: database-design relational-database


【解决方案1】:

根据您的评论,我认为您只需对数据使用位和位运算符即可获利。

如果您的查询看起来像“为我找到在这些时隙中的任何一个可用的用户”或“为我找到在所有这些时隙中可用的用户”,那么您可以按位得到-AND。

在 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 位),它是一个非常直接的映射到你的“实时”中的类似编码" 数据结构,如果你有的话。并且完全相同的操作给出完全相同的结果。

【讨论】:

    【解决方案2】:

    我的设计与众不同。跟大家分享一下;

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

    【讨论】:

      猜你喜欢
      • 2012-09-17
      • 2015-06-26
      • 2020-05-14
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 2019-04-17
      • 2012-04-29
      • 1970-01-01
      相关资源
      最近更新 更多