Я работаю над CTE, который вычисляет повторяемость недели, но у меня возникают некоторые проблемы, когда узор пересекает год.T-SQL Рассчитать повторяемость даты
СТЕ должен Вычислить все случаи, основанные на следующих параметрах:
- Рецидив Count - сколько раз это будет происходить
- дни недели - в какой день недели он произойдет
- Дата начала - , когда начнется расчет рисунков
- Периодичность - Как часто в терминах недель, т.е. 1 раз в неделю, 2 каждые 2 недели
- Начало недели - Неделя номер первого вхождения, который отражает столбец Start Date
Это, как я хранить образцы:
/*
Pattern Table
*/
CREATE TABLE Pattern (
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY
, [Subject] [nvarchar](100) NULL
, [RecurrenceCount] [int] NULL
, [WeekDays] [varchar](max) NULL
, [StartDate] [datetime] NULL
, [EndDate] [datetime] NULL
, [Periodicity] [int] NULL
, [StartingWeek] [int] NULL
);
Ниже несколько моделей я использую, чтобы проверить мой КТР:
/*
Pattern samples for test
*/
Insert into Pattern Values (N'Every 5 Weeks Fri, Sat, Sun', 72, 'Friday, Saturday, Sunday', N'2016-12-02', N'2016-12-02', 5, datepart(wk, N'2016-12-02'));
Insert into Pattern Values (N'Every 3 Weeks Tue, Wed, Thu', 20, 'Tuesday, Wednesday, Thursday', N'2016-11-01', N'2016-11-01', 3, datepart(wk, N'2016-11-01'));
Я начинаю отсчет считая первый день недели понедельник
SET DATEFIRST 1
И это КТР я использую для запуска этого вычисления:
/*
Display Patterns
*/
select * from Pattern
DECLARE @mindate DATE = (SELECT MIN(StartDate) FROM Pattern)
DECLARE @maxmindate DATE = (SELECT MAX(StartDate) FROM Pattern)
DECLARE @maxcount INT = (SELECT MAX(RecurrenceCount) FROM Pattern)
DECLARE @maxdate DATE = DATEADD(WK, @maxcount + 10, @maxmindate)
/*
CTE to generate required occurrences
*/
;With cteKeyDate As (
Select
KeyStartDate = @MinDate,
KeyDOW = DateName(WEEKDAY, @MinDate),
KeyWeek = datepart(WK,@MinDate)
Union All
Select
KeyStartDate = DateAdd(DD, 1, df.KeyStartDate) ,
KeyDOW = DateName(WEEKDAY,DateAdd(DD, 1, df.KeyStartDate)),
KeyWeek= DatePart(WK,DateAdd(DD, 1, df.KeyStartDate))
From cteKeyDate DF
Where DF.KeyStartDate <= @MaxDate
)
SELECT
Id, KeyStartDate, KeyDow, KeyWeek, RowNr, OccNr = ROW_NUMBER() OVER (PARTITION BY Id ORDER BY StartDate)
FROM
(Select
A.Id
,A.StartDate
,A.EndDate
,Count = A.RecurrenceCount
,Days = A.WeekDays
,Every = A.Periodicity
,KeyStartDate = CASE
/*
if no periodicity (1) then it is sequential
if periodicity, first week doesn't apply (MIN KeyWeek)
*/
WHEN A.Periodicity = 1
OR (Periodicity <> 1 AND (SELECT MIN(C.StartingWeek) FROM Pattern AS C WHERE C.Id = A.Id) = KeyWeek)
THEN KeyStartDate
/* Otherwise formula ADD WEEKS => Current Week Min Week */
ELSE
DATEADD(WK, ((A.Periodicity - 1) * (KeyWeek - (SELECT MIN(C.StartingWeek) FROM Pattern AS C WHERE C.Id = A.Id))) , KeyStartDate)
END
,KeyDow
,KeyWeek
,RowNr = Row_Number() over (Partition By A.Id Order By B.KeyStartDate)
,Periodicity = A.Periodicity
from
Pattern A
Join cteKeyDate B on B.KeyStartDate >= DATEADD(DAY, -1, A.StartDate) and Charindex(KeyDOW, A.WeekDays) > 0
) Final
Where
RowNr <= Count AND Id = 1
Option (maxrecursion 32767)
Теперь, если я проверяю снова мой шаблоны, например, первый, я получаю этот результат, который имеет ошибку, когда события происходят в следующем году. RowNr 15 ошибочен, потому что это должно произойти 23 апреля (воскресенье), а не на следующей неделе.
Id KeyStartDate KeyDow KeyWeek RowNr OccNr
1 02.12.2016 Friday 49 1 1
2 03.12.2016 Saturday 49 2 2
3 04.12.2016 Sunday 49 3 3
4 06.01.2017 Friday 50 4 4
5 07.01.2017 Saturday 50 5 5
6 08.01.2017 Sunday 50 6 6
7 10.02.2017 Friday 51 7 7
8 11.02.2017 Saturday 51 8 8
9 12.02.2017 Sunday 51 9 9
10 17.03.2017 Friday 52 10 10
11 18.03.2017 Saturday 52 11 11
12 19.03.2017 Sunday 52 12 12
13 21.04.2017 Friday 53 13 13
14 22.04.2017 Saturday 53 14 14
15 28.04.2013 Sunday 1 15 15
16 31.05.2013 Friday 2 16 16
17 01.06.2013 Saturday 2 17 17
Хотя второй образец рассчитан просто отлично. Я думаю, что у меня есть проблема в логике, когда шаблон пересекает год и количество недель сбрасывается до 0 в SQL, но я не могу найти решение, я боролся сейчас в течение нескольких дней.
Вы можете выполнить код с образцами here.
В качестве точки отсчета, вам не нужно, что 'Разбиение BY' в вашем' ROW_NUMBER' и * пожалуйста * не срабатывают код с 'Ā',' b', 'C 'табличные псевдонимы. – iamdave
@iamdave о псевдонимах, я не использую A, B, C, но A означает «действия», поэтому есть известный псевдоним . О PARTITION BY необходимо иначе, если запрос выполняется по нескольким шаблонам на определенном SQL-сервере, таком как 2008, строки не упорядочены правильно – Raffaeu
Можете ли вы объяснить, что пытается сделать CTE, то, что вы пытаетесь сделать здесь, это поможет нам лучше понять ваш код, в настоящее время дата начала и дата окончания одинаковы в вашем шаблоне стол, не могли бы вы попытаться рассказать нам, что вы пытаетесь выполнить здесь. – Surendra