Wie nehme ich einen Tag des Jahres und bucket es in Wochen des Jahres in Microsoft SQL? Verwenden in den Fertigungsszenarien für den Materialbedarf
-
03-07-2019 - |
Frage
Ich habe eine Notwendigkeit, einen Bruttobedarf Bericht zu erstellen, wie viel Angebot und Nachfrage eines Artikel im Bestand ab von einem Startdatum dauert und ‚Eimer‘ in verschiedene Wochen des Jahres, so dass Disponenten wissen, wann sie brauchen ein Punkt, und wenn sie zu dieser Zeit im Lager genug Lager haben.
Als Beispiel der heutige Datum (Bericht Datum) ist 8/27/08. Der erste Schritt ist das Datum für den Montag der Woche des Bericht Datum fällt zu finden. In diesem Fall Montag 8/25/08 wäre. Dies wird der erste Tag des ersten Eimer. Alle Transaktionen, die vor, die fallen werden Woche # 0 zugeordnet und wird als Anfangssaldo für den Bericht zusammengefasst werden. Die restlichen Eimer werden von diesem Punkt berechnet. Zum achten Eimer gibt es kein Enddatum so dass alle Transaktionen nach dem 8.en Eimer Startdatum Woche # 8 berücksichtigt werden.
WOCHE # Beginn Ende
0 ....... Keine .......... 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 ...... Keine
Wie kann ich die Woche # bekommen, Startdatum, Enddatum für ein bestimmtes Datum?
Lösung
Sie können Montag erhalten für einen bestimmten Zeitpunkt in einer Woche als:
DATEADD(d, 1 - DATEPART(dw, @date), @date)
und Sie können eine gespeicherte Prozedur mit dem folgenden Körper
schreiben-- 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
Wenn ich pass
@date = '20080827'
zu diesem Verfahren, erhalte ich die folgende
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
Andere Tipps
Ich habe immer gefunden, ist es am einfachsten und effizientesten (für SQL Server) eine Tabelle mit einer Zeile für jede Woche in die Zukunft durch Ihren Domain-Horizont zu konstruieren; und kommen zu, dass (mit einem "WHERE GETDATE ()> = MONDATE UND NICHT VORHANDEN (SELECT 1 FROM Tabelle WHERE MONDATE Alles, was Sie versuchen, mit UDF zu tun, wird viel weniger effizient, und ich finde schwieriger zu bedienen.
- SQL setzt den ersten Tag der Woche als Sonntag und für unsere Zwecke wollen wir es Montag sein
.
--Dieser Befehl tut das.
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
Das Problem, das ich mit dem einem Eimer zu einem Zeitpunkt Ansatz zu sehen ist, dass sein schwer es Maßstab zu machen,
Wenn Sie in einer benutzerdefinierten Funktion beitreten werden Sie eine bessere Leistung erhalten, können Sie diese aa verwenden Ausgangspunkt
Warum nicht eine Kombination von DATEPART (Jahr, Datum-Spalte) und DATEPART (Woche, Datum-Spalte) und die Gruppe durch diese Werte verwenden. Dies funktioniert, wenn die Woche in DATEPART montags als ISO 8601 ausgerichtet ist, erfordert. Kurz umrissen:
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...