создание календаря с не начальными и конечными датами года в sql - PullRequest
0 голосов
/ 23 августа 2011

Мне нужно создать календарь на год, который начинается и заканчивается на определенную дату.Он не начинается 1-го января и не заканчивается 31-го декабря, а скорее в даты, которые могут меняться от года к году (я объявляю / устанавливаю их программно).Это календарь для школы (учебный год).В настоящее время в следующем году он начнется 1 октября и закончится 30 сентября.Что мне нужно, это порядковый номер недели, начало недели и дату конца недели, и все даты между .

Таким образом, за первую неделю 2011/2012 учебного года (1 октября - 30 сентября) я получу week number = 1, week start date = 2011-10-01 и week end date = 2011-10-02 (в основном два ряда для каждого дня на этой неделе) и т. Д.

Проблема, с которой я столкнулся, заключается в том, что при использовании встроенных функций Microsoft Date и Time я получаю, например, только номер недели в «диапазоне года по умолчанию»:

DATEPART(ww, [Date])

Верхний уровень, если я сдам 1 октября, вернется 40. Но мой результат должен быть 1.

Есть какие-нибудь предложения, как это сделать?В настоящее время у меня есть таблица со всеми датами по годам (по умолчанию годы с 1990 до 2100), номера недель по умолчанию и месяцы в нем.Я думал о выборе диапазонов дат (это были бы даты начала и окончания моего учебного года) из него и назначении правильных дат недели и дат начала и окончания.

И нет, это не какой-то школьный проект или домашняя работа, этодля моей работы:)

Ответы [ 2 ]

1 голос
/ 23 августа 2011

Ответ [t-clausen.dk] достаточно хорош, но вам понадобятся EndOfWeek и BeginOf Week:

DECLARE @start DATETIME
DECLARE @end DATETIME

SET @start = '2011-10-01'
SET @end = '2012-9-30';

WITH cte(calendardate, week, beginofweek, endofweek)
     AS (SELECT @start         calendardate,
                CAST(1 AS INT) week,
                Dateadd(DAY, 0, Datediff(DAY, 0, @start) -
                                Datediff(DAY, 0, @start) %
                                7)
                               beginofweek,
                Dateadd(DAY, 6, Datediff(DAY, 0, @start) -
                                Datediff(DAY, 0, @start) %
                                7)
         UNION ALL
         SELECT calendardate + 1,
                week + CASE
                         WHEN Datediff(DAY, 0, calendardate) %7 = 6 THEN 1
                         ELSE 0
                       END,
                Dateadd(DAY, 0, Datediff(DAY, 0, calendardate + 1) -
                                Datediff(DAY, 0, calendardate + 1) % 7)
                beginofweek,
                Dateadd(DAY, 6, Datediff(DAY, 0, calendardate) -
                                Datediff(DAY, 0, calendardate) % 7)
         FROM   cte
         WHERE  calendardate < @end)
SELECT CAST(calendardate AS DATE) calendardate,
       week,
       CAST(beginofweek AS DATE)  beginofweek,
       CAST(endofweek AS DATE)    endofweek
FROM   cte
OPTION( MAXRECURSION 0) 

Результат:

calendardate week        beginofweek endofweek
------------ ----------- ----------- ----------
2011-10-01   1           2011-09-26  2011-10-02
2011-10-02   1           2011-09-26  2011-10-02
2011-10-03   2           2011-10-03  2011-10-02
2011-10-04   2           2011-10-03  2011-10-09
2011-10-05   2           2011-10-03  2011-10-09
2011-10-06   2           2011-10-03  2011-10-09
2011-10-07   2           2011-10-03  2011-10-09
2011-10-08   2           2011-10-03  2011-10-09
2011-10-09   2           2011-10-03  2011-10-09
2011-10-10   3           2011-10-10  2011-10-09
2011-10-11   3           2011-10-10  2011-10-16
2011-10-12   3           2011-10-10  2011-10-16
2011-10-13   3           2011-10-10  2011-10-16
2011-10-14   3           2011-10-10  2011-10-16
2011-10-15   3           2011-10-10  2011-10-16
2011-10-16   3           2011-10-10  2011-10-16
2011-10-17   4           2011-10-17  2011-10-16
2011-10-18   4           2011-10-17  2011-10-23

...

2012-09-21   52          2012-09-17  2012-09-23
2012-09-22   52          2012-09-17  2012-09-23
2012-09-23   52          2012-09-17  2012-09-23
2012-09-24   53          2012-09-24  2012-09-23
2012-09-25   53          2012-09-24  2012-09-30
2012-09-26   53          2012-09-24  2012-09-30
2012-09-27   53          2012-09-24  2012-09-30
2012-09-28   53          2012-09-24  2012-09-30
2012-09-29   53          2012-09-24  2012-09-30
2012-09-30   53          2012-09-24  2012-09-30
1 голос
/ 23 августа 2011

После прочтения вашего вопроса я снова придумал это

declare @start datetime
declare @end datetime

set @start = '2011-10-01'
set @end = '2012-9-30'

;with cte as
(
select @start firstday, @start + 6 - DATEDIFF(day, 0, @start) %7 lastday,  1 week
union all
select lastday + 1, case when @end < lastday + 7 then @end else lastday + 7 end,  week + 1
from cte
where lastday < @end
)
select cast(firstday as date) firstday, cast(lastday as date) lastday, week  from cte
option(MAXRECURSION 0) 

Результат:

firstday   lastday    week
---------- ---------- ----
2011-10-01 2011-10-02 1
2011-10-03 2011-10-09 2
2011-10-10 2011-10-16 3
2011-10-17 2011-10-23 4
....
2012-09-17 2012-09-23 52
2012-09-24 2012-09-30 53

Старая гипертензия

declare @start datetime
declare @end datetime

set @start = '2011-10-01'
set @end = '2012-9-30'

;with cte as
(
select @start calendardate, 1 week
union all
select calendardate + 1, week + case when DATEDIFF(day, 0, calendardate) %7 = 6 then 1 else 0 end
from cte
where calendardate < @end
)
select cast(calendardate as date) calendardate, week  from cte
option(MAXRECURSION 0) 

Результат:

calendardate week
------------ -----------
2011-10-01   1
2011-10-02   1
2011-10-03   2
2011-10-04   2
2011-10-05   2
2011-10-06   2
2011-10-07   2
2011-10-08   2
2011-10-09   2
2011-10-10   3
2011-10-11   3
2011-10-12   3
.....
2012-09-29   53
2012-09-30   53
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...