【问题标题】:Script to filter by most recent end of week date按最近的周末日期过滤的脚本
【发布时间】:2018-07-12 22:37:15
【问题描述】:

我公司的报告周是周一到周日。周一早上,我使用 Microsoft SQL Server Management Studio 运行了几个查询,以报告前一周的业务活动。我目前使用声明语句来提取所需的日期范围。只要我在星期一运行报告,这就会很好地工作。但是,如果星期一是节假日并且直到星期二我才生成报告,我需要手动修改每个查询的日期范围。如何修改我的日期过滤器以检索上一个“星期日”的记录,这样我实际运行报告的日期并不重要。

这是一个示例查询;

Declare @DATEFROM SMALLDATETIME = (CONVERT(datetime, getdate() + cast('00:00' as datetime)) - 8), @DATETO smalldatetime = (CONVERT(datetime, getdate() + cast('23:59' as datetime))-2);

Create Table #SALES ([PartNumber] CHAR(5), [DateSold] SMALLDATETIME)

Insert Into #SALES   Select   '10190',  '6/3/2018 11:00'
Insert Into #SALES   Select   '10213',  '6/8/2018  8:00:00 AM'
Insert Into #SALES   Select   '10214',  '6/5/2018  9:30:00 AM'
Insert Into #SALES   Select   '10215',  '6/4/2018  1:00:00 PM'
Insert Into #SALES   Select   '10217',  '6/6/2018  1:00:00 PM'
Insert Into #SALES   Select   '10219',  '6/7/2018  12:00:00 PM'
Insert Into #SALES   Select   '10220',  '6/9/2018  3:30:00 PM'

Insert Into #SALES   Select   '10221',  '6/11/2018  8:30:00 AM'
Insert Into #SALES   Select   '10222',  '6/11/2018  2:30:00 PM'
Insert Into #SALES   Select   '10225',  '6/8/2018  8:00:00 AM'
Insert Into #SALES   Select   '10227',  '6/10/2018  9:00:00 AM'
Insert Into #SALES   Select   '10231',  '6/10/2018  1:00:00 PM'
Insert Into #SALES   Select   '10233',  '6/2/2018  8:00:00 AM';

SELECT S.PartNumber, S.DateSold 
FROM #SALES S 
WHERE DATESOLD BETWEEN @DATEFROM AND @DATETO 
ORDER BY DateSold;

DROP TABLE #SALES

【问题讨论】:

    标签: sql-server sql-date-functions


    【解决方案1】:

    首先,一些感兴趣的项目:

    • SQL Server 的SET DATEFIRST 命令允许您选择任何工作日作为一周的第一天,从 1(星期一)到 7(星期日)。
    • 您可以使用表达式@@datefirst查询此设置的当前值。
    • DATEPART(weekday, getdate()) 将返回当前工作日的数字,其中 1 表示 SET DATEFIRST 设置的日期,2 表示后一天,以此类推。

    假设我想回答这个问题:在某个任意日期@TestDate 之前的多少天是最近的星期一?自最近一周开始以来经过的天数是DATEPART(weekday, @TestDate) - 1,而从星期一到一周开始之间经过的天数是@@datefirst - 1,因此从最近经过的天数最近的星期一是这些数量模 7 的总和:

    declare @TestDate date = convert(date, getdate());
    declare @DaysPastMonday int = (@@datefirst + datepart(weekday, @TestDate) - 2) % 7;
    

    有了这些信息,你可以很容易地得到你的日期范围:

    declare @DateTo date = dateadd(day, -@DaysPastMonday, @TestDate);
    declare @DateFrom date = dateadd(day, -7, @DateTo);
    

    但请注意,我在这里选择的两个日期都是星期一,而您想要的是星期一到星期日。我这样做的原因是,如果您要查看可能具有时间组件和日期的字段(例如,datetimedatetime2),并且您想使用 @ 987654334@,那么您需要确保您的结束日期具有 SQL Server 能够表示的最新时间。我发现使用包含开始日期且不包含结束日期的日期范围更简洁。所以代替这样的表达式:

    x BETWEEN @DateFrom AND @DateTo
    

    您可以编写查询以使用如下表达式:

    x >= @DateFrom AND x < @DateTo
    

    【讨论】:

    • 谢谢理查德。我非常感谢您在回复中提供的详细信息!
    【解决方案2】:
    Declare @DATEFROM datetime = DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 0), 
    @DATETO datetime = DATEADD(ms, -3, (select DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 7)));
    

    【讨论】:

    • 感谢您的回复 Matthew,这正是我想要的。我是新近自学的,我知道我的知识存在一些差距,但我相信我遵循了这个逻辑,并且我今天在每周报告中成功地使用了它。我什至修改了几个月至今的报告。我有一个后续问题,我不需要在报告上显示时间戳,但我确实想确保所有订单都按日历日期捕获,而不是当前日期时间减去 X 天。该声明声明是否符合该要求?。
    • 嗨,K-Jo,抱歉,好久没上,刚刚找到您的后续问题。如果我正确理解您的问题,代码应该没问题。我会在您的 UI 或实际报告的打印中截断时间戳,但会将它们保留在您的 WHERE 子句中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    相关资源
    最近更新 更多