2015-02-11 53 views
-2

我目前正在處理一個計劃問題,我需要能夠爲特定任務創建計劃,其中某些任務可能具有日期參數,這些日期參數需要與計劃運行時相關但我不是確定這些應該如何存儲在數據庫中(SQL Server)。在數據庫中存儲相對日期值

例如:任務A計劃在每個月的第二天運行,並要求參數StartDateEndDate的值。計劃運行時,StartDate應該是上個月的22日,而EndDate是上個月的最後一天。

有沒有這樣的東西的任何當前實現供參考?

UPDATE: 我所問的是你將如何代表「每月的第一個」值「每月的最後」,「上月的第2個」,內等「的2個月前第一次」一個數據庫,以便它可以用來計算相對於特定日期的日期。

我知道如何使用DATE函數來計算這些值,但這些需要以某種方式在數據庫中表示並正確/有效地進行解析。我確信我不是第一個遇到這種情況的人。

+0

我不確定我是否理解這裏的問題?你想知道如何找到像上個月的最後一天那樣的事情嗎?這裏是一些常見的日期時間例程的鏈接。 http://www.sqlservercentral.com/blogs/lynnpettis/2009/03/25/some-common-date-routines/ – 2015-02-11 15:31:21

+0

請參閱更新的問題。 – mheptinstall 2015-02-11 19:16:26

+0

表示相對日期的一種方式:http://programmers.stackexchange.com/a/78883/111526 – mheptinstall 2015-02-11 19:39:56

回答

0

基於在這個答案中發佈的想法here我創建了以下模式和查詢來計算正確的日期。

該查詢將被轉換爲內嵌表值函數,該函數將接受@Id@RelativeToDate的參數。

DayOfWeekNumber將保持1-7的值,其中1 =星期一,7 =星期日,函數應該計算正確的結果,而不管@@DATEFIRST

目前在表格中沒有指定約束條件,但確實應該確保表格中只存在有效條目。

DECLARE @RelativeDate TABLE 
(
    Id     INT IDENTITY(1,1) 
    , Name    VARCHAR(100) 
    , DayOfWeekNumber TINYINT 
    , DayOfMonthNumber TINYINT 
    , LastDayOfMonth BIT 
    , DayOffset   SMALLINT 
    , WeekOffset  SMALLINT 
    , MonthOffset  SMALLINT 
    , YearOffset  SMALLINT 
) 

INSERT INTO @RelativeDate 
(
    Name 
    , DayOfWeekNumber 
    , DayOfMonthNumber 
    , LastDayOfMonth 
    , DayOffset 
    , WeekOffset 
    , MonthOffset 
    , YearOffset 
) 

VALUES 
    ('1st of previous month', 0, 1, 'FALSE', 0, 0, -1, 0) 
, ('Last of previous month', 0, 0, 'TRUE', 0, 0, -1, 0) 
, ('1st of current month', 0, 1, 'FALSE', 0, 0, 0, 0) 
, ('Last of current month', 0, 0, 'TRUE', 0, 0, 0, 0) 
, ('7th of current month', 0, 7, 'FALSE', 0, 0, 0, 0) 
, ('8th of current month', 0, 8, 'FALSE', 0, 0, 0, 0) 
, ('14th of current month', 0, 14, 'FALSE', 0, 0, 0, 0) 
, ('21th of current month', 0, 21, 'FALSE', 0, 0, 0, 0) 
, ('22th of current month', 0, 22, 'FALSE', 0, 0, 0, 0) 
, ('28th of current month', 0, 28, 'FALSE', 0, 0, 0, 0) 
, ('29th of current month', 0, 29, 'FALSE', 0, 0, 0, 0) 
, ('This Sunday', 7, 0, 'FALSE', 0, 0, 0, 0) 
, ('Next Sunday', 7, 0, 'FALSE', 0, 1, 0, 0) 
, ('Last Sunday', 7, 0, 'FALSE', 0, -1, 0, 0) 


DECLARE 
    @Date  DATE = GETDATE() 

SELECT 
    * 
    , DATENAME(WEEKDAY, DateValue) AS WeekDayName 

FROM 
    @RelativeDate 
    CROSS APPLY(VALUES(
     DATEADD(DAY, DayOffset, 
      DATEADD(WEEK, WeekOffset, 
       DATEADD(MONTH, MonthOffset, 
        DATEADD(YEAR, YearOffset, @Date)))) 
    )) AS OffsetDate(OffsetDate) 
    CROSS APPLY(VALUES(
     CASE 
      WHEN LastDayOfMonth = 'TRUE' 
       THEN DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, OffsetDate) + 1, 0)) 
      -- If the month doesn't have the day of the month number then return NULL 
      WHEN DayOfMonthNumber <> 0 AND DayOfMonthNumber > DATEPART(DAY, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, OffsetDate) + 1, 0))) 
       THEN NULL 
      WHEN DayOfMonthNumber <> 0 AND DATEPART(DAY, OffsetDate) > DayOfMonthNumber 
       THEN DATEADD(DAY, DayOfMonthNumber - DATEPART(DAY, OffsetDate), OffsetDate) 
      WHEN DayOfMonthNumber <> 0 AND DATEPART(DAY, OffsetDate) < DayOfMonthNumber 
       THEN DATEADD(DAY, DayOfMonthNumber - DATEPART(DAY, OffsetDate), OffsetDate) 
      WHEN DayOfWeekNumber <> 0 
       THEN DATEADD(DAY, DayOfWeekNumber - (((DATEPART(WEEKDAY, OffsetDate) + @@DATEFIRST - 1 - 1) % 7) + 1), OffsetDate) 
     END 
    )) AS DateValue(DateValue)