Hoe kan ek 'n dag van die jaar en 'emmer dit in weke van die jaar in Microsoft SQL? Gebruik in die vervaardiging van scenario's vir wesenlike vereistes
-
03-07-2019 - |
Vra
Ek het 'n behoefte aan 'n bruto vereistes verslag dat hoeveel vraag en aanbod van 'n item in voorraad en verder neem van 'n begin datum en 'emmers' dit in verskillende weke van die jaar te skep sodat materiaal beplanners weet wanneer hulle nodig sal hê 'n item en as hulle genoeg voorraad in voorraad op daardie tydstip.
As 'n voorbeeld, vandag se datum (verslag datum) is 8/27/08. Die eerste stap is om die datum vir die Maandag van die week die verslag datum val in vind. In hierdie geval, sal Maandag 8/25/08 wees. Dit word die eerste dag van die eerste emmer. Alle transaksies wat voor daardie val is aan week # 0 en sal saamgevat word as die begin balans vir die verslag. Die oorblywende emmers word bereken vanaf daardie punt. Vir die agtste emmer, is daar geen einde datum so enige transaksies daarna 8 emmer begin datum word beskou week # 8.
WEEK # begin einde
0 ....... Geen .......... 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 ...... Geen
Hoe kry ek die week #, begin datum, einddatum vir 'n gegewe datum?
Oplossing
Jy kan kry Maandag vir 'n gegewe datum in 'n week as:
DATEADD(d, 1 - DATEPART(dw, @date), @date)
en jy kan 'n gestoor proses met die volgende liggaam skryf
-- 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
Wanneer ek slaag
@date = '20080827'
teen hierdie prosedure Ek kry die volgende
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
Ander wenke
Ek het nog altyd gevind dat dit die maklikste en mees doeltreffende (vir SQL Server) om 'n tafel te bou met 'n ry vir elke week in die toekoms deur jou domein horison; en sluit om wat (met 'n "WAAR GETDATE ()> = MONDATE EN NIE BESTAAN (SELECT 1 van die tafel WAAR MONDATE Enigiets wat jy probeer om te doen met UDF se sal baie minder doeltreffend wees en ek het iets uitgevind moeilik om te gebruik.
- SQL stel die eerste dag van die week as Sondag en vir ons doeleindes ons wil hê dit moet Maandag
.
--This opdrag doen dit.
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
Die probleem wat ek sien met die een emmer op 'n slag benadering is dat dit is moeilik om dit skaal maak,
As jy aansluit by 'n gebruiker-gedefinieerde funksie wat jy sal beter prestasie kry, kan jy hierdie aa gebruik beginpunt
Hoekom nie 'n kombinasie van DATEPART (jaar, datum-kolom) en DATEPART (week, datum-kolom) en groep gebruik deur hierdie waardes. Dit werk as die week in DATEPART is in lyn op Maandae as ISO 8601 vereis. In uiteensetting:
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...