Como faço para tirar um dia do ano e "balde é em semanas do ano no Microsoft SQL? Utilizado na fabricação de cenários para as necessidades de material

StackOverflow https://stackoverflow.com/questions/419372

  •  03-07-2019
  •  | 
  •  

Pergunta

Eu tenho uma necessidade para criar um necessidades brutas relatam que leva o quanto a oferta ea demanda de um item no inventário a partir de uma data de início em diante e 'baldes' TI em diferentes semanas do ano para que os planejadores de materiais saber quando eles vão precisar um item e se eles têm estoque suficiente no inventário naquele momento.

Como exemplo, a data de hoje (data do relatório) é 8/27/08. O primeiro passo é encontrar a data para a segunda-feira da semana a data do relatório cai. Neste caso, de segunda seria 8/25/08. Isto torna-se o primeiro dia do primeiro balde. Todas as transacções que caem antes que são atribuídos a semana # 0 e vai ser resumido como o saldo inicial para o relatório. Os baldes restantes são calculados a partir desse ponto. Pela oitava balde, não há nenhuma data final para que todas as transações depois disso 8ª data de início balde são consideradas semana # 8.

SEMANA # Início Fim DATA
0 ....... Nenhum .......... 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 ...... Nenhum

Como faço para obter a semana #, data, data de término para uma determinada data?

Foi útil?

Solução

Você pode obter segunda-feira qualquer data para em uma semana como:

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

e você pode escrever um procedimento armazenado com o seguinte corpo

-- 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

Quando eu passar

@date = '20080827'

para este procedimento, recebo a seguinte

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

Outras dicas

Eu sempre achei mais fácil e eficiente (para SQL Server) para construir uma tabela com uma linha para cada semana para o futuro através de seu horizonte de domínio; e junte-se a isso (com um "ONDE GETDATE ()> = MONDATE E NÃO EXISTE (SELECT 1 FROM tabela WHERE MONDATE

Qualquer coisa que você tentar fazer com UDF de será muito menos eficiente e eu acho mais difícil de usar.

- SQL define o primeiro dia da semana como domingo e para os nossos propósitos que nós queremos que ele seja segunda-feira
. --Este comando faz isso.

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

O problema que vejo com o balde em uma abordagem de tempo é que é difícil fazê-lo escala,

Se você entrar em uma função definida pelo usuário que você irá obter um melhor desempenho, você poderia usar esta aa ponto de partida

Por que não usar uma combinação de DATEPART (ano, data-coluna) e DATEPART (semana, data-coluna) e grupo por esses valores. Isso funciona se a semana em DATEPART está alinhado às segundas-feiras, como ISO 8601 requer. Em linhas:

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...
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top