在数据库中,如果只需要年份和月份,你会使用日期字段还是年份和月份字段?

9
我正在设置一张表格,需要年份和月份。在MySQL中,我认为有两个选项:(1)两个字段:一个用于年份,一个用于月份,或者(2)一个日期字段(日期始终为1)。
两个字段的优点是速度较快(我认为),因为MySQL不必将值从日期转换为整数,尽管这可能是微不足道的。日期字段的优点是“自动”验证:某人无法将数据输入数据库,其中月份为13或年份为1。使用日期字段,您还可以更轻松地进行日期计算(例如,计算月份之间的差距)。
你会使用哪一个?或者你会使用其他的方法吗?

1
еҜ№дәҺеӣһжқҘзҡ„д»»дҪ•дәәпјҢжҲ‘жҺЁиҚҗдҪҝз”ЁEXTRACT(YEAR_MONTH FROM mydate)иҝӣиЎҢжҜ”иҫғе’ҢдҪҝз”ЁDATE_FORMAT(mydate,'%Y-%M')иҝӣиЎҢжҳҫзӨәпјҢиҜ·еҸӮи§Ғж—ҘжңҹеҮҪж•°гҖӮ - KCD
10个回答

20

使用日期字段。由于 SQL 原生支持日期字段,因此可以使用 WHERE 子句轻松过滤特定日期。

这两个字段具有某些优势,可以使其速度更快[...]

您的 SELECT 查询不是瓶颈,所以不必担心这个问题。可读性和实用程序比“感知瓶颈”更重要。


1
我大部分都同意,但如果列名为“year”和“month”,那么可读性问题在哪里? - Learning
1
SELECT [...] WHERE date between '02-01-2009' AND '04-31-2010' 转换为 SELECT [...] WHERE Year BETWEEN 2009 AND 2010 AND Month BETWEEN 2 AND 4。 - MrValdez
2
那些SELECT语句并不相同。第二个只获取了2009年和2010年的第2、3和4个月; 这与获取14个月的数据完全不同。 - NotMe
@Chris 我得承认我的话不对。经过第二次检查,我的SQL语句有缺陷。 - MrValdez
3
当我第一次阅读您的答案时,我不同意,但是您无意中证明了自己的观点,因为当您使用单独的月份和年份列时,很容易搞砸SQL。 :) - Ryan Lundy
显示剩余3条评论

1

如果您要在日期字段上运行大量操作,那么我建议将其拆分为单独的列,并在表约束或数据访问层中处理数据验证。

例如,按天、月、年构建销售报告时,如果字段被拆分,则效率更高。原因是您不必使用日期时间函数来拆分日期以进行分组。

如果是像生日这样的东西,我可能只会偶尔查询它,那么我就不会担心它,只需将其保留在日期字段中即可。


1

即使您只需要年份和月份,我仍然会使用日期字段,因为收集所有数据不会有任何损失。作为标准做法,我总是尽可能地收集所有数据。


1
我会使用单独的列,主要是因为这样可以更好地利用索引。例如,如果您只关心给定月份(而不是年份)的数据,则我认为在日期时间列上创建索引并没有帮助。

除非MySQL有什么"特别"的地方,否则它应该可以。或者我应该说它"可能"。 - David Aldridge

1

虽然对您目前可能没有用处,但IBM Informix Dynamic Server支持以下类型:

DATETIME YEAR TO MONTH

这个存储了你想要的 - 年份和月份。它有其用途。DATETIME 类型族包括许多其他类型,偶尔也会有它们的用处 - 还有一些边缘效用的类型,典型的例子是 DATETIME MONTH TO MINUTE。(该类型的缺点是需要冗长的符号来操作它,但是任何或所有 DATETIME 类型都可以执行许多操作。)

在许多 DBMS 中,您可以对列设置约束条件,因此如果您采用两列方法,则应在列上放置一个 CHECK(month_column BETWEEN 1 AND 12) 约束条件,以确保用户未在表中放置无效值。您甚至可以在年份列上应用约束条件。

此外,一些 DBMS 允许您创建用户定义的类型,年-月类型在这些类型中非常简单。当然,具体细节取决于 DBMS。


1

除非将年份和月份分开存储具有特定的性能优势,否则建议使用日期。关于索引,如果您有两个列,则需要创建一个组合列的索引,而不是仅针对日期列的索引。日期将在内部转换为长整型值,因此所需的存储空间实际上并不是问题。

此外,请考虑两个字段可能带来的维护痛点。您将拥有两个数据库字段,可能是对象上的两个字段或者需要构建/解析月份和年份以便与数据库交互。使用日期保持简单,并让数据库跟踪数据完整性。

我处理类似您描述的数据 - 过期日期,其中日期始终是该月的最后一天,因此我们只需要月份和年份。我们将其存储为日期。


1

我会保留一个日期时间列和两个计算列,分别是月份和年份(当然要建立索引)。这样既能达到我的目的,又不失优雅。


1

如果你预计会有这样的查询:“给我所有七月份的行,不管是哪一年的”,使用单独的月份和年份列会更容易编写。为月份列建立一个单独的索引应该可以提高查询速度。

否则,我会选择单个日期列:简单、易懂、内置验证和日期计算函数可用。你唯一需要担心的是,新设计人员可能会想知道为什么所有事件都发生在每个月的第一天。

还有另一个使用单独的月份和年份列的原因,那就是当月份未知时。我曾经在允许“在2009年某个时候”这种即将到来的事件的应用程序中使用过它。在这种情况下,使用月份列中的NULL可以很好地解决问题。除非你想出一些可怕的方法,比如1月2日表示月份未知,否则无法使用日期类型列来实现这一点。


1

这样想一下:总有一天会有人向你提出一个需求,希望增强应用程序的功能,不仅能保存年份和月份,还要保存日期。

那么,你会为日期再添加一个额外的列吗?

接着,他们可能还会要求你保存时间。

如果你有单独的年/月/日三个列,那么增强功能会有多容易?如果只有一个日期列呢?

基于这个原因,我会选择使用一个日期列。


0

可能不行,因为SQL Server(Microsoft)中最小的日期时间数据类型是smalldatetime,长度为4个字节。如果您只需要月份和年份,则需要1个字节的月份和2个字节的年份。


可能不是吧?我是二选一的:P - Darryl Hein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接