8

这是一个完全假设的问题:假设我有一个数据库,我需要在其中存储用户的会员资格,该会员资格可以持续特定的时间(1 个月、3 个月、6 个月、1 年等)。

拥有一个包含字段的表是否更好Memberships(每个日期都存储为 unix 时间戳):

user_id INT, start_date INT,end_date INT

或将其存储为:

user_id INT, start_date INT,length INT

无论哪种方式,您都可以查询具有活动成员资格的用户(例如)。对于后一种情况,每次运行查询时都需要执行算术运算,而前一种情况只需要计算一次结束日期(插入时)。从这个角度来看,以前的设计似乎更好——但它有什么缺点吗?是否有任何常见问题可以通过存储长度来避免,而不能通过存储日期来避免?

此外,在存储时间/日期数据时,unix 时间戳是要走的路吗,还是喜欢 DATETIME 之类的东西?我遇到了两种数据类型(过度转换)的问题,但通常选择 unix 时间戳。如果喜欢 DATETIME 之类的东西,这将如何改变我之前的设计问题的答案?

4

6 回答 6

2

我不同意。我会有一个开始和结束日期 - 节省每次执行计算。

于 2012-05-01T13:56:36.753 回答
2

如果取决于您是否要索引结束日期,这又取决于您要如何查询数据。

如果你这样做了,并且你的 DBMS 不支持基于函数的索引或计算列上的索引,那么你唯一的办法就是拥有一个物理的end_date,这样你就可以直接索引它。

除此之外,我看不出有什么不同。

顺便说一句,使用您的 DBMS 提供的本机日期类型,而不是int. 首先,您将获得某种类型的安全性(因此,如果您尝试在预期日期的位置读取/写入 int,则会收到错误),防止您创建不匹配的引用完整性(尽管日期上的 FK 很少见) ,它可以处理时区(取决于 DBMS),DBMS 通常会为您提供提取日期组件等的功能......

于 2012-05-01T14:07:29.187 回答
2

这实际上取决于您将针对您的日期运行什么类型的查询。如果查询涉及按开始/结束时间或日期范围搜索,那么开始/和日期肯定会选择第一个选项。

如果您对统计数据更感兴趣(什么是平均会员期?有多少人成为会员超过一年?)那么我会选择第二个选项。

关于过度转换-您正在编程哪种语言?Java/Ruby 在后台使用 Joda Time,它大大简化了与日期/时间相关的逻辑。

于 2012-05-01T14:10:14.387 回答
1

从设计的角度来看,我发现有一个开始日期和成员资格的长度是一个更好的设计。

结束日期是会员开始日期 + 持续时间的派生值。这就是我的想法。

于 2012-05-01T13:53:54.653 回答
1

这两种策略在功能上是等效的,选择你喜欢的。

于 2012-05-01T13:57:12.677 回答
0

如果成员资格可能会随着时间的推移而切换,我建议使用此选项:

user_id INT, 
since_date DATE, 
active_membership BIT

active_membership状态是随着时间的推移而切换的状态,并且正在since_date跟踪这种情况发生的时间。此外,如果您有一组有限的允许成员长度,并且需要跟踪某个用户选择了哪个长度,则可以将其扩展为:

user_id INT, 
since_date DATE, 
active_membership BIT, 
length_id INT

wherelength_id将引用可用和允许的成员资格长度的查找表。但是,请注意,在这种情况下,since_date如果可以更改您的会员期限,则会变得模棱两可。在这种情况下,您将不得不进一步扩展它:

user_id INT, 
active_membership_since_date DATE, 
active_membership BIT, 
length_since_date DATE,
length_id INT

使用这种方法很容易看出,当两个日期异步更改时,规范化会失效。为了保持这种标准化,您实际上需要 6NF。如果您的要求朝着这个方向发展,我建议您查看Anchor 建模

于 2015-11-06T14:56:06.107 回答