Sql server 在Microsoft SQL中,我如何将一年中的一天和一年中的几周进行“存储”?用于材料要求的制造场景

Sql server 在Microsoft SQL中,我如何将一年中的一天和一年中的几周进行“存储”?用于材料要求的制造场景,sql-server,datediff,dateadd,Sql Server,Datediff,Dateadd,我需要创建一份总需求报告,从开始日期开始计算库存中某个项目的供应量和需求量,并将其“存储”到一年中的不同周,以便物料计划人员知道何时需要某个项目,以及当时是否有足够的库存 例如,今天的报告日期为8/27/08。第一步是查找报告日期所在周的星期一的日期。在这种情况下,周一将是2008年8月25日。这将成为第一个桶的第一天。在此之前的所有交易记录都分配给第0周,并将汇总为报告的期初余额。其余铲斗从该点开始计算。对于第八个bucket,没有结束日期,因此第八个bucket开始日期之后的任何交易都被视为

我需要创建一份总需求报告,从开始日期开始计算库存中某个项目的供应量和需求量,并将其“存储”到一年中的不同周,以便物料计划人员知道何时需要某个项目,以及当时是否有足够的库存

例如,今天的报告日期为8/27/08。第一步是查找报告日期所在周的星期一的日期。在这种情况下,周一将是2008年8月25日。这将成为第一个桶的第一天。在此之前的所有交易记录都分配给第0周,并将汇总为报告的期初余额。其余铲斗从该点开始计算。对于第八个bucket,没有结束日期,因此第八个bucket开始日期之后的任何交易都被视为第8周

周开始日期结束日期 0…………无…………2008年8月24日 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 2008年10月13日……无


如何获取给定日期的一周、开始日期和结束日期?

-SQL将一周的第一天设置为星期天,出于我们的目的,我们希望它是星期一。 -这个命令可以做到这一点

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

我认为一次一桶的方法存在的问题是很难实现规模化


如果您加入一个用户定义的函数,您将获得更好的性能,您可以使用

我一直发现,SQL Server在未来通过您的域范围为每周构造一行表是最简单和最有效的;并使用WHERE GETDATE>=MONDATE且不存在从WHERE MONDATE
您尝试使用UDF进行的任何操作都会大大降低效率,我发现使用起来更困难。

您可以在一周内的任何给定日期获得星期一,如下所示:

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
对于这个过程,我得到了以下结果

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

为什么不结合使用DATEPARTyear、date列和DATEPARTweek、date列和group by这些值呢。如果按照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...

从dbo中选择*fnGetDateRanges'd'、'2006-01-01 11:10:00'、'2006-01-05 08:00:00'并不难使用。。。总的来说,我发现UDF的性能已经足够好了,您也可以使用UDF填充horizon表。我一直发现UDF break SARG和TSQL日期算法需要掌握。但是,如果您不习惯使用TSQL日期表达式,就足以构建表了。YYMV.:DI有足够的数据800000行左右,很容易从一开始创建临时表或使用已经构建的UDF切换到这两种方式,我可以测试这两种方式,看看哪种更快。不要将其设置为临时表-将其设置为永久表,以便可以正确索引。让我们知道您发现了什么:这里没有参数,UDF效率较低,但根据问题的不同,它们的效率可以足够高,而且代码有时可以更好地阅读,它们肯定比一次只做一行更有效……很抱歉,我没有指定将其放在用户函数中。如果不是这样的话,这会使家长程序变得非常混乱!我喜欢这样的想法:根据你帖子中的评论,将桶范围放入临时表中,然后将其查询掉,而不是反复调用函数。确保你也向临时表添加了适当的索引,否则这可能会变成梨形。没有临时表-永久索引表。UDF和temp表都是糟糕的mojo。过去,UDF本质上是SP,最后每行调用一个SP——尽管编译后很难看。我很想知道索引临时表和索引永久表之间的性能差异是什么。。。它应该只相当于创建表、索引表和重新编译计划的时间。通常,对于这类报告,您会看到许多秒的执行时间,其主要优点是简化了执行单元。见其他类似注释。
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...