2015-02-11 3 views
-2

В настоящее время я имею дело с проблемой планирования, когда мне нужно иметь возможность создавать расписания для конкретных задач, где некоторые задачи могут иметь параметры даты, которые должны быть относительно того, когда расписание выполняется, хотя я не что они должны храниться в базе данных (SQL Server).Сохранять относительные значения даты в базе данных

Например: Задача A планируется запустить 2-го числа каждого месяца и требует значений для параметров StartDate и EndDate. Когда выполняется расписание, StartDate должен быть 22 числа предыдущего месяца, а EndDate - последний день предыдущего месяца.

Есть ли какие-либо текущие реализации чего-то подобного для справки?

UPDATE: То, что я спрашиваю, как вы могли бы представлять ценность «Первый месяц», «Последний из месяца», «второй предыдущего месяца», «первая из 2 месяца назад» и т.д. в базу данных, чтобы ее можно было использовать для вычисления даты относительно конкретной даты.

Я знаю, как их вычислять с использованием функций DATE, но они должны быть как-то представлены в базе данных и корректно проанализированы. Я уверен, что я не первый человек, столкнувшийся с подобным сценарием.

+0

Я не уверен, что понял здесь вопрос? Вы пытаетесь выяснить, как найти такие вещи, как последний день предыдущего месяца и что-то вроде этого? Вот ссылка на ряд общих подпрограмм datetime. http://www.sqlservercentral.com/blogs/lynnpettis/2009/03/25/some-common-date-routines/ –

+0

См. обновленный вопрос. – mheptinstall

+0

Один из способов представления относительных дат: http://programmers.stackexchange.com/a/78883/111526 – mheptinstall

ответ

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) 
Смежные вопросы