Как взять день года и «распределить его по неделям года» в Microsoft SQL? Используется в производственных сценариях для требований к материалам - PullRequest
1 голос
/ 07 января 2009

У меня есть потребность в создании отчета о валовых потребностях, в котором берется объем спроса и предложения на товар в инвентаре с даты начала и далее, и «складывает» его в разные недели года, чтобы специалисты по планированию материалов знали, когда им потребуется предмет, и если в это время у него достаточно запасов в инвентаре.

Например, сегодняшняя дата (отчетная дата) - 27.08.08. Первый шаг - найти дату понедельника недели, в которую попадает дата отчета. В этом случае понедельник будет 25.08.08. Это становится первым днем ​​первого ведра. Все транзакции, которые выпадают до этого, назначаются на неделю # 0 и будут суммироваться как начальное сальдо для отчета. Остальные ведра рассчитываются от этой точки. Для восьмого сегмента дата окончания не существует, поэтому любые транзакции после этой даты начала 8-го блока считаются неделей № 8.

НЕДЕЛЯ # НАЧАЛО ДАТЫ КОНЕЦ
0 ....... Без .......... 8/24 / 08
1 ....... 8/25/08 ....... 8/31/08
2 ....... 9/1/08 ......... 9/7/08
3 ....... 9/8/08 ......... 9/14/08
4 ....... 9/15/08 ....... 9/21 / 08
5 ....... 9/22/08 ....... 9/28 / 08
6 ....... ....... 9/29/08 10/5/08
7 ....... 10/06/08 ..... 10/12/08
8 ....... 10/13/08 ...... нет

Как получить номер недели, дату начала, дату окончания для данной даты?

Ответы [ 5 ]

2 голосов
/ 07 января 2009

Мне всегда было проще и эффективнее (для SQL Server) создать таблицу с одной строкой на каждую неделю в будущем через горизонт вашего домена; и присоединиться к нему (с помощью "WHERE GETDATE ()> = MONDATE И НЕ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ таблицы WHERE MONDATE

Все, что вы попытаетесь сделать с UDF, будет гораздо менее эффективным, и я считаю, что его будет сложнее использовать.

1 голос
/ 07 января 2009

Вы можете получить понедельник на любую дату недели как:

DATEADD(d, 1 - DATEPART(dw, @date), @date)

и вы можете написать хранимую процедуру со следующим телом

-- find Monday at that week
DECLARE @currentDate SMALLDATETIME
SELECT @currentDate = DATEADD(d, 1 - DATEPART(dw, @date), @date)

-- create a table and insert the first record
DECLARE @weekTable TABLE (Id INT, StartDate SMALLDATETIME, EndDate SMALLDATETIME)
INSERT INTO @weekTable VALUES (0, NULL, @currentDate)

-- increment the date
SELECT @currentDate = DATEADD(d, 1, @currentDate)

-- iterate for 7 more weeks
DECLARE @id INT
SET @id = 1
WHILE @id < 8
BEGIN
    INSERT INTO @weekTable VALUES (@id, @currentDate, DATEADD(d, 6, @currentDate))
    SELECT @currentDate = DATEADD(ww, 1, @currentDate)
    SET @id = @id + 1
END

-- add the last record
INSERT INTO @weekTable VALUES (8, @currentDate, NULL)

-- select the values
SELECT Id 'Week #', StartDate 'Start Date', EndDate 'End Date'
FROM @weekTable

Когда я прохожу

@date = '20080827'

к этой процедуре я получаю следующее

Week #  Start Date     End Date
0   NULL                2008-08-24 00:00:00
1   2008-08-25 00:00:00 2008-08-31 00:00:00
2   2008-09-01 00:00:00 2008-09-07 00:00:00
3   2008-09-08 00:00:00 2008-09-14 00:00:00
4   2008-09-15 00:00:00 2008-09-21 00:00:00
5   2008-09-22 00:00:00 2008-09-28 00:00:00
6   2008-09-29 00:00:00 2008-10-05 00:00:00
7   2008-10-06 00:00:00 2008-10-12 00:00:00
8   2008-10-13 00:00:00 NULL
0 голосов
/ 07 января 2009

Почему бы не использовать комбинацию DATEPART (год, столбец даты) и DATEPART (неделя, столбец даты) и группировать по этим значениям. Это работает, если неделя в DATEPART выровнена по понедельникам, как того требует ISO 8601. В общих чертах:

SELECT DATEPART(year, date_column) AS yyyy,
       DATEPART(week, date_column) AS ww,
       ...other material as required...
    FROM SomeTableOrOther
    WHERE ...appropriate filters...
    GROUP BY yyyy, ww -- ...and other columns as necessary...
0 голосов
/ 07 января 2009

Проблема, которую я вижу с одним ведром за один раз, состоит в том, что трудно сделать его масштабируемым,

Если вы присоединитесь к пользовательской функции, вы получите лучшую производительность, вы можете использовать это отправная точка

0 голосов
/ 07 января 2009

- SQL устанавливает первый день недели как воскресенье, и для наших целей мы хотим, чтобы это был понедельник.
- Эта команда делает это.

SET DATEFIRST 1

DECLARE 
    @ReportDate DATETIME, 

    @Weekday INTEGER, 
    @NumDaysToMonday INTEGER, 
    @MondayStartPoint DATETIME,
    @MondayStartPointWeek INTEGER,
    @DateToProcess DATETIME,
    @DateToProcessWeek INTEGER,
    @Bucket VARCHAR(50),
    @DaysDifference INTEGER,
    @BucketNumber INTEGER,
    @NumDaysToMondayOfDateToProcess INTEGER,
    @WeekdayOfDateToProcess INTEGER,
    @MondayOfDateToProcess DATETIME,
    @SundayOfDateToProcess DATETIME

SET @ReportDate = '2009-01-01'
print @ReportDate

SET @DateToProcess = '2009-01-26'
--print @DateToProcess

SET @Weekday = (select DATEPART ( dw , @ReportDate ))
--print @Weekday

--print DATENAME(dw, @ReportDate)

SET @NumDaysToMonday = 
    (SELECT
      CASE 
         WHEN @Weekday =  1 THEN 0
         WHEN @Weekday =  2 THEN 1
         WHEN @Weekday =  3 THEN 2
         WHEN @Weekday =  4 THEN 3
         WHEN @Weekday =  5 THEN 4
         WHEN @Weekday =  6 THEN 5
         WHEN @Weekday =  7 THEN 6
      END)

--print @NumDaysToMonday

SET @MondayStartPoint =  (SELECT DATEADD (d , -1*@NumDaysToMonday, @ReportDate))
--print @MondayStartPoint

SET @DaysDifference = DATEDIFF ( dd , @MondayStartPoint , @DateToProcess )
--PRINT @DaysDifference

SET @BucketNumber = @DaysDifference/7
--print @BucketNumber

----Calculate the start and end dates of this bucket------
PRINT 'Start Of New Calc'

print @DateToProcess

SET @WeekdayOfDateToProcess = (select DATEPART ( dw , @DateToProcess ))
print @WeekdayOfDateToProcess

SET @NumDaysToMondayOfDateToProcess= 
    (SELECT
      CASE 
         WHEN @WeekdayOfDateToProcess =  1 THEN 0
         WHEN @WeekdayOfDateToProcess =  2 THEN 1
         WHEN @WeekdayOfDateToProcess =  3 THEN 2
         WHEN @WeekdayOfDateToProcess =  4 THEN 3
         WHEN @WeekdayOfDateToProcess =  5 THEN 4
         WHEN @WeekdayOfDateToProcess =  6 THEN 5
         WHEN @WeekdayOfDateToProcess =  7 THEN 6
      END)

print @NumDaysToMondayOfDateToProcess
SET @MondayOfDateToProcess =  (SELECT DATEADD (d , -1*@NumDaysToMondayOfDateToProcess, @DateToProcess))
print @MondayOfDateToProcess   ---This is the start week

SET @SundayOfDateToProcess = (SELECT DATEADD (d , 6, @MondayOfDateToProcess))
PRINT @SundayOfDateToProcess
...