在数据库中仅保存日期和月份的最佳方式

问题描述:

我们必须保存每年一次的重复事件的日期和月份。 (把它当作他们当年的发票发送给客户的那一天。)在数据库中仅保存日期和月份的最佳方式

我们将不得不使用这些信息做一些计算。例如,如果客户每年支付两次。那么我们不仅需要检查今天是否是今天,而且如果这一天是在6个月内。

我们现在有几种选择: a)我们将信息保存在日期字段中,但忽略年份。 b)我们在数据库date_day和date_month中创建两个int字段。 c)我们创建一个varchar字段,然后做一个正则表达式和分割例如每次我们做一些计算时,每次都会增加31.12。

我们做了几个测试,发现c)肯定太慢了。但我们仍然有选择a)和b)。首先我们想要去b),但经过一些测试后,我们更倾向于a)。

是否有一个很好的技术原因会真正使一个选项比另一个好得多?

(我们使用目前的MySQL,如果这是很重要的。)

我会选择B),因为它更准确地反映了数据的含义。有一些数据结构中的某些部分应该被“忽略”是有问题的。如果人们只是简单地进行日期比较,假设年份总是相同,但是有人使用了不同的占位符年份,假设年份无关紧要?

始终使用反映您意图的数据结构。

这c)是坏的,我相信,超出合理的讨论:-)。我并没有想到性能的原因...

+0

同意,其在那里它的部分都应该被忽略的数据字段是非常糟糕的,很可能会在未来咬你。我投赞成票b。 – 2009-06-25 10:55:30

+0

是的,这一年并不重要。我们已经有合同开始日期和合同结束日期。我们只需要计算是否必须发送发票。我们正在做的第一个选择是检查“今天”是否在开始日期和结束日期之内。只有这样我们才能检查我们是否必须今天生成发票。 – 2009-06-25 14:01:54

我也想与b),但使用TINYINT的月份(0至255)和SMALLINT(-32,768至32,767)为一年,以节省一点空间。

选择一个int字段,如1月1日的1601。

+0

这个选项和“31.12”有什么区别? – 2009-06-25 10:55:38

+0

计算而不是字符串操作 – 2009-06-25 11:02:00

+0

正确,但你也可以把它作为一个实数存储 – 2009-06-25 11:20:44

我会选择b),因为这会使查询变得更加容易:您将能够以非常简单的方式恢复范围内(12月,特定日期,日期范围)内的所有事件。 如果您选择a) - 为了比较和提取的原因,不要忘记将年份设置为特定的年份。

我会使用日期字段,即使不需要,仍然可以节省一年。只需将其打印出来/使用它即可。有几个方面的原因:

  1. 你可能会发现,后面的 点的客户不希望你 保存日期。在这种情况下,您不需要对您的 数据库结构进行任何更改。
  2. 如果需要,您可以使用SQL日期函数来比较日期。如果您的日期和月份位于不同的字段中,则需要更多代码计算两个日期(闰年等)之间的差异。

选择b)的原因也可以用SQL日期函数轻松解决。例如,在一个查询中,您可以轻松选择某个月的事件。

我会存储第一个事件的日期,然后每个后续事件的间隔,有点像大多数日历应用程序。在这种情况下,你会构建这样的:

first_event | interval | interval_unit 
-------------+-------------------------- 
    2009-01-01 |  6 | 'month' 
    2009-02-01 |  1 | 'year' 

不幸的是,MySQL不具有INTERVAL数据类型,所以两列,一位后处理的将是必要的,但我认为这是最灵活的方式来解决问题。

我会去天的年数(例如,从0到365,然后单号添加到特定年份的1月1日你感兴趣的内容。

如果您不想做上面的解决方案的额外数学,然后使用两个字段一个月和一个日期(但确保您在需要时更新两个!)。

请记住,您必须处理闰年,所以使用日期字段是一个坏主意,因为你必须存储两年的日期 - 一个闰年,一个不是 - 非常复杂!

我也面对sa我的问题,在我的情况,我需要根据特定的日期在一个月内被重复。我每年用于“日期”和这样的查询

SELECT * FROM test_table WHERE MONTH(date) = 1 AND DAY(date) = 14

结果这样

enter image description here检索数据

优势

  1. 我可以使用MySQL的能力。
  2. 减少客户端计算。
  3. 可以使用DATE_FIELD其他计算

我的建议是用这种方式

,这可能是有帮助的人