كيف يمكنني اتخاذ يوم من أيام السنة و'دلو انه في الأسابيع من السنة في Microsoft SQL؟ المستخدمة في التصنيع سيناريوهات لتلبية الاحتياجات المادية
-
03-07-2019 - |
سؤال
ولدي حاجة لإنشاء تقرير احتياجات الإجمالي الذي يأخذ كم العرض والطلب على بند في المخزون من تاريخ بدء فصاعدا و "دلاء" أنه في الأسابيع مختلفة من السنة بحيث يعرف المخططين المادي عندما ستحتاج عنصر وإذا كان لديهم مخزون كاف في المخزون في ذلك الوقت.
وعلى سبيل المثال، تاريخ اليوم (تاريخ التقرير) هو 8/27/08. الخطوة الأولى هي العثور على موعد يوم الاثنين من الاسبوع تاريخ التقرير يقع في. في هذه الحالة، سوف يكون الاثنين 8/25/08. هذا يصبح في اليوم الأول من المجموعة الأولى. يتم تعيين كافة المعاملات التي تقع قبل ذلك لمدة أسبوع و# 0 وسيتم تلخيصها الرصيد بداية التقرير. وتحسب الدلاء المتبقية من تلك النقطة. لدلو الثامن، لا يوجد تاريخ انتهاء لذلك تعتبر أي معاملات بعد ذلك التاريخ دلو بداية 8TH الأسبوع رقم 8.
وWEEK # تاريخ البدء تاريخ الانتهاء
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 ...... لا يوجد
وكيف يمكنني الحصول على أسبوع #، تاريخ، تاريخ انتهاء بدء لتاريخ معين؟
المحلول
ويمكنك الحصول على الاثنين لأي تاريخ معين في الأسبوع على النحو التالي:
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
نصائح أخرى
ولقد وجدت دائما أن من الأسهل والأكثر فعالية (ل SQL Server) لبناء جدول مع صف واحد كل أسبوع في المستقبل من خلال الأفق نطاقك. وينضم إلى ذلك (مع "حيث GETDATE ()> = MONDATE AND NOT EXISTS (SELECT 1 من الجدول حيث MONDATE وأي شيء تحاول أن تفعل مع لUDF سيكون أقل كفاءة بكثير، وأجد أكثر صعوبة للاستخدام.
و- SQL يحدد اليوم الأول من الأسبوع، الأحد ولأغراضنا نحن نريد أن يكون الاثنين
.
قيادة --This يفعل ذلك.
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
والمشكلة أرى مع دلو واحد على نهج الوقت هو أن من الصعب أن تجعل من الحجم،
إذا كنت الانضمام الى وظيفة المعرفة ستحصل على أداء أفضل، يمكنك استخدام هذا أأ نقطة انطلاق
لماذا لا تستخدم مزيجا من 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...