比较日期并将其设置为“一周的第一天”或“新的一个月”

Compare dates and set it as "first day of the Week" or "new Month"

提问人:brins 提问时间:8/23/2023 最后编辑:Tsahi Asherbrins 更新时间:8/24/2023 访问量:139

问:

目前,我正在操作日期列并将其设置为一周的第一天。示例:2023 年 8 月 23 日将设置为 2023 年 8 月 20 日,使用 但是,在这种情况下,有些日期属于新月份,例如:2023 年 9 月 1 日,它被分配给 2023 年 8 月 27 日,但它应该被分配给新的月份计算。我该如何计算? 我正在使用 SQL Server:select DATEADD(day, 1-DATEPART(WEEKDAY,'2023/08/25'), '2023/08/25')

Microsoft SQL Azure (RTM) - 12.0.2000.8 7月 8, 2023 12:00:47**

我可以通过任何方式比较月份,如果它大于当前月份,那么它就会被分配给新的下周?

任何帮助将不胜感激!

DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01')` -- assigns to first week

case
    when DATEPART(MONTH,DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01')) > DATEPART(MONTH, GETDATE()) THEN "assign it to new month"
else DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01') 

这就是我所期望的,它将月份数字与当前月份进行比较,如果它更大,则分配给新月份,否则它分配给第一周。DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01')

输入 输出 评论
2023-08-23 00:00:00.000 2023-08-20 00:00:00.000 一周的第一天,即 SQL Server 中的星期日
2023-09-01 00:00:00.000 2023-09-03 00:00:00.000 新月份的第一天,因为该日期属于新月份,即使它在日历上是八月的最后一周
sql-server 日期时间 azure-sql-database

评论

0赞 Panagiotis Kanavos 8/23/2023
日期是二进制值,而不是像 .为避免不幸的转换,请使用日期文本的 either 或 for。列的实际类型是什么? ?另外,逻辑是什么?本周的开始 8 月 28 日。您要求的是本周的开始时间或月份的开始时间,以较大者为准2023/09/012023-09-0120230901date2023-09-02
0赞 siggemannen 8/23/2023
我认为如果您以以下形式附加一个 Markdown 表会有所帮助:“输入值”、“预期输出值”。确保包括所有不同的情况。我很确定这个问题已经解决了很多次,你真的搜索过stackoverflow吗?
0赞 Panagiotis Kanavos 8/23/2023
解决日历相关问题的快速方法是创建一个日历表,其中包含 10-20 年的预先计算日期以及分析和报告所需的额外列,例如 Year、Month、Semester、Quarter、WeekNumber、StartOfMonth、StartOfWeek 等。您可以在任何类型列上联接此表,并按所需的任何时间段进行聚合,并轻松执行例如季度与季度或同比的比较。date
2赞 Thom A 8/23/2023
当你使用的是 Azure SQL 数据库时,为什么不用于获取一周的第一天呢?DATETRUNC
2赞 Thom A 8/23/2023
“一周的第一天,即 SQL Server 中的星期日”事实并非如此,您使用的语言设置决定了一周的第一天。例如,对我来说,返回 ,而不是 .如果我是美国人,那么它会返回后者。对于 ISO 周,它始终是星期一。db<>小提琴DATETRUNC(WEEK,GETDATE())2023-08-212023-08-20

答:

0赞 JosephStyons 8/23/2023 #1

以下是两种方法;一种是纯 SQL,另一种是 UFN。

--Just using a SELECT statement (no non-native functions)
declare @d datetime = '2023-09-01 00:00:00.000'
select
  format(
    case when month(@d) = month(dateadd(day,1-datepart(weekday,@d),@d))
         then dateadd(day,1-datepart(weekday,@d),@d)
         else dateadd(day,8-datepart(weekday,DATEADD(month, DATEDIFF(month,0,@d),0)),DATEADD(month, DATEDIFF(month,0,@d),0))
    end
  ,'d') as "Date, rounded down to most recent Sunday (or first Sunday of the month)"
/*
Output:
9/3/2023
*/
go
if object_id('UFN_DATEROUNDDOWN') is not null
  drop function UFN_DATEROUNDDOWN
go
create function UFN_DATEROUNDDOWN
(
  @d datetime
)
returns datetime
as
begin
  --Given a date, return date of the first day of that week (Sunday).
  --UNLESS
  --that would cause the date to roll back into a prior month.
  --in that case, return the 1st sunday of the month instead.
  declare @weekstart datetime = dateadd(day,1-datepart(weekday,@d),@d)
  declare @monthstart datetime = DATEADD(month, DATEDIFF(month,0,@d),0)
  declare @firstweekstart_newmonth datetime = dateadd(day,8-datepart(weekday,@monthstart),@monthstart)
  
  return
    case when month(@d) = month(@weekstart)
         then @weekstart
         else @firstweekstart_newmonth
    end
end
go
declare @d datetime
declare @r table(inputdate datetime, outputdate datetime)
set @d = '2023-08-20';insert into @r select @d,dbo.ufn_daterounddown(@d)
set @d = '2023-08-21';insert into @r select @d,dbo.ufn_daterounddown(@d)
set @d = '2023-08-22';insert into @r select @d,dbo.ufn_daterounddown(@d)
set @d = '2023-08-23';insert into @r select @d,dbo.ufn_daterounddown(@d)
set @d = '2023-09-01';insert into @r select @d,dbo.ufn_daterounddown(@d)
set @d = '2023-09-02';insert into @r select @d,dbo.ufn_daterounddown(@d)
set @d = '2023-09-03';insert into @r select @d,dbo.ufn_daterounddown(@d)
SELECt
  format(inputdate,'d')  as "Input date"
 ,format(outputdate,'d') as "Output date"
FROM
  @R
/*
Results:
Input date | Output date
========================
8/20/2023  | 8/20/2023
8/21/2023  | 8/20/2023
8/22/2023  | 8/20/2023
8/23/2023  | 8/20/2023
9/1/2023   | 9/3/2023
9/2/2023   | 9/3/2023
9/3/2023   | 9/3/2023
*/

评论

0赞 brins 8/23/2023
我如何将 9 月 1 日日期分配给新月的新周?这是 @JosephStyons 年 9 月 3 日
0赞 brins 8/23/2023
正如我的问题一样,我 9 月 1 日的输出应该是 9 月 3 日(新月份的一周的第一天或“下周的第一天”)
0赞 JosephStyons 8/23/2023
@brins我刚刚根据您的澄清更新了答案。
0赞 Thom A 8/23/2023
为什么 2023-09-03 要返回 2023-09-01,@brins?2023-09-03 是一周的第一天,那你为什么要回到月初呢?
1赞 krishna 8/24/2023 #2

请根据您的要求找到以下工作代码。除了你的逻辑之外,我一个人修改了一点。如果到达日期的月份小于给定日期的月份,则添加 7 天(这将给出新月的第一个星期日)。如果它适合您,请将其标记为答案。让我知道结果。

SELECT
    CASE
        WHEN DATEPART(MONTH,DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01')) < DATEPART(MONTH, '2023/09/01')
        THEN DATEADD(day, 7, DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01'))
        ELSE DATEADD(day, 1-DATEPART(WEEKDAY,'2023/09/01'), '2023/09/01') 

评论

0赞 krishna 8/24/2023
当然,这可以进一步优化。但是,如果对您有用,请告诉我!!