Come faccio a prendere un giorno dell'anno e "seccarlo" in settimane dell'anno in Microsoft SQL? Utilizzato negli scenari di produzione per i requisiti di materiale

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

  •  03-07-2019
  •  | 
  •  

Domanda

Ho bisogno di creare un rapporto sui fabbisogni lordi che tenga conto della quantità e della domanda di un articolo nell'inventario a partire da una data di inizio in poi e lo "raggruppa" in diverse settimane dell'anno in modo che i pianificatori del materiale sappiano quando ne avranno bisogno un articolo e se in quel momento hanno abbastanza scorte nell'inventario.

Ad esempio, oggi & # 8217; la data di s (data del rapporto) è il 27/08/08. Il primo passo è trovare la data per il lunedì della settimana in cui cade la data del rapporto. In questo caso, lunedì sarebbe il 25/08/08. Questo diventa il primo giorno del primo secchio. Tutte le transazioni che precedono vengono assegnate alla settimana # 0 e verranno riepilogate come saldo iniziale per il report. I restanti bucket vengono calcolati da quel punto. Per l'ottavo bucket, non esiste una data di fine, pertanto qualsiasi transazione successiva all'ottava data di inizio del bucket viene considerata la settimana n. 8.

WEEK # INIZIO DATA FINE DATA
0 ....... Nessuno .......... 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 ...... Nessuno

Come posso ottenere la settimana #, la data di inizio, la data di fine per una determinata data?

È stato utile?

Soluzione

Puoi ricevere il lunedì per una determinata data in una settimana come:

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

e puoi scrivere una procedura memorizzata con il seguente 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 passo

@date = '20080827'

a questa procedura, ottengo quanto segue

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

Altri suggerimenti

Ho sempre trovato più semplice ed efficiente (per SQL Server) costruire una tabella con una riga per ogni settimana nel futuro attraverso il tuo orizzonte di dominio; e unisciti a quello (con un " WHERE GETDATE () > = MONDATE E NON ESISTE (SELEZIONA 1 DA tabella DOVE MONDATE < GETDATE ()) ".

Qualunque cosa tu cerchi di fare con l'UDF sarà molto meno efficiente e trovo più difficile da usare.

--SQL imposta il primo giorno della settimana come domenica e per i nostri scopi vogliamo che sia lunedì.
- Questo comando lo fa.

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

Il problema che vedo con l'approccio a un secchio alla volta è che è difficile ridimensionarlo,

Se ti unisci a una funzione definita dall'utente otterrai prestazioni migliori, puoi utilizzare questo aa punto di partenza

Perché non utilizzare una combinazione di DATEPART (anno, colonna della data) e DATEPART (settimana, colonna della data) e raggruppare in base a questi valori. Questo funziona se la settimana in DATEPART è allineata il lunedì come ISO 8601 richiede. In sintesi:

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...
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top