在日历表

时间:2015-06-22 14:04:23

标签: sql-server calendar

我正在使用日历表来保存日期信息。我的初步目的是确定工作日和休假日(包括周末和假日)。表中的字段是

  • 日期(主键)
  • 日(没有后缀的第1,第2,第3等)
  • 类型(工作日,周六,周日等)

使用年,月和日字段起初看起来特别有用,尤其是设置假期,但事后我想我可以使用DATEPART(yyyy, [Date])来获得年份以及同样的月和日。是否有任何其他用于拥有这些字段?

如果表现会影响到多大的影响?日历表只有100年的数据,约为36,500条记录,有些叶子可以预设100年,每年可以设置一些不同日期(约5条记录)的年份。是否值得考虑性能差异?

摘要

使用单独的字段来保存年,月和日信息是否有任何用处,性能差异是否足以让人感到困扰?

编辑1

从执行计划来看,我甚至没有看到任何性能差异,所以主要是这些领域还有其他用途吗?

编辑2

有些人似乎误解了这个问题。我的问题不是如何创建日历表或关于日历表中字段的意见。我的问题是, ANY 是否使用[Year][Month][Day]字段。

2 个答案:

答案 0 :(得分:1)

日历表很小。正如您所指出的那样,即使您明确地存储了年份和月份,您所说的存储的千字节也要覆盖100年。行宽不是问题。

如果确实保留了它们,请将它们设为计算列以强制与[date]保持一致。如果您希望它们也存在,请将它们保存为计算列。

CREATE TABLE Calendar (
  [date] date NOT NULL PRIMARY KEY
 ,[year]  AS ISNULL(DATEPART(year,[date]),0)
 ,[month] AS ISNULL(DATEPART(month,[date]),0)
 ,[day]   AS ISNULL(DATEPART(day,[date]),0)
 ,[type] int NOT NULL DEFAULT 0
)

DECLARE @date_from date = '2000-01-01'
DECLARE @date_to   date = '2099-12-31'

INSERT Calendar ([date])
SELECT TOP(1+DATEDIFF(day,@date_from, @date_to))
  DATEADD(day,ROW_NUMBER() OVER(ORDER BY (SELECT 1))-1,@date_from)
FROM master.dbo.spt_values a, master.dbo.spt_values b

答案 1 :(得分:0)

我经历过这种过程的几次不同的迭代,这就是我过去实现它的方式。

这是一个起点。在每场比赛中,停止处理进一步的规则。

  • 如果是周六,那就是周末。
  • 如果是星期天,那就是周末。
  • 如果是1月1日,那就是假期(新年)。
  • 如果是1月2日,那是星期一,那就是假期(观察新年)。
  • 如果是1月的第3个星期一,那就是假期(MLK日)。
  • 如果是2月的第3个星期一,那就是假期(总统日)。
  • 如果是五月的最后一个星期一,那就是假期(阵亡将士纪念日)。
  • 如果是7月3日,那是星期五,那就是假期(观察独立日)。
  • 如果是7月4日,那就是假期(独立日)。
  • 如果是7月5日,那是星期一,那就是假期(观察独立日)。
  • 如果是九月的第一个星期一,那就是假期(劳动节)。
  • 如果是10月的第2个星期一,那就是假日(哥伦布日)。
  • 如果是11月10日,那是星期五,那就是假期(观察退伍军人节)。
  • 如果是11月11日,那就是假期(退伍军人节)。
  • 如果是11月12日,那是星期一,那就是假期(退伍军人节)。
  • 如果是11月的第4个星期四,那就是假期(感恩节)。
  • 如果是11月的第4个星期五而且不是11月22日,那就是假期(黑色星期五)。
  • 如果是11月29日,那是星期五,那就是假期(黑色星期五)。
  • 如果是12月24日,那是星期五,那就是假期(平安夜)。
  • 如果是12月25日,那是假期(圣诞节)。
  • 如果是12月26日,那是星期一,那就是假期(节礼日)。
  • 如果是12月31日,那是星期五,那就是假期(新年前夜)。
  • 如果上述条件均不适用,则为工作日。

通过这种方式,您可以遍历规则并确定工作日,周末和假日。您可以使用以下字段存储这些规则:

  • 日期
  • 星期几
  • 周数

以下是该算法的工作原理。

  • 如果[Year] > 0,此规则仅影响该年的日期;否则,无论年份如何,此规则都有效。
  • 如果[Month] > 0,此规则仅影响该月的日期;否则,无论月份如何,此规则都有效。
  • 如果[Day Of Month] > 0 AND [Day of Week] == 0,则此规则会影响该月当天的日期。
  • 如果[Day of Month] == 0 AND [Day of Week] > 0,此规则会影响当天某一天的日期。
  • 如果[Day of Month] == 0 AND [Day of Week] > 0 AND [Week Number] > 0 AND [Week Number] < 6,此规则会影响[Week Number] [Day of Week]基本实例。例如,如果[Day of Week] = @Monday[Week Number] = 1,则此规则会影响该月的第一个星期一。
  • 如果[Day of Month] > 0 AND [Day of Week] > 0 AND [Week Number] > 0 AND [Week Number] < 6,此规则会影响[Week Number][Day of Week]的{​​{1}}基本实例。如果[Day of Month]的{​​{1}}基数实例落在[Week Number]之前,则此规则会影响[Day of Week] [Day of Month]的基本实例。我将此介绍给黑色星期五的算法。
  • 如果[Week Number] + 1[Day of Week]以及[Day of Month] == 0,此规则会影响一个月内[Day of Week] > 0的最后一个实例。

使用此算法和这22条规则,您不必为所有内容存储条目。这将涵盖您一个世纪以来的所有美国联邦假期。您可以为请求的假期添加具有确切日期的条目([Week Number] == 6[Day of Week][Year])。