如何从月份计算前一年的同一天假设每月的第一个星期一将是去年该月的第一个星期一

时间:2021-05-25 03:04:25

标签: sql sql-server tsql

如何计算与去年相同的星期几,例如今年 5 月的第一个星期一将是去年 5 月的第一个星期一,依此类推。

SELECT 
    ADD_MONTHS(CURRENT_DATE, -12) + 
        ((SELECT day_of_week 
          FROM sys_calendar.calendar 
          WHERE calendar_date = CURRENT_DATE) -
          (SELECT day_of_week 
           FROM sys_calendar.calendar 
           WHERE calendar_date = ADD_MONTHS(CURRENT_DATE, -12)))

我做了上面的事情,但是对于像 2021 年 4 月 7 日这样的日期是一个月的第一个星期三,2020 年 4 月 8 日是一个月的第二个星期三,但我希望计算 2020 年 4 月 1 日。

样本是

2021/4/7 to 2020/4/1
2021/4/14 to 2020/4/8

我想要的这种计算

2 个答案:

答案 0 :(得分:2)

我有一个可能对您有用的建议,尽管上面的所有评论和查询都是正确的。
如果您所说的是您系统中的常见查询,并且不是您现在想要查询的内容,我建议您在数据库中创建一个 Dim_Date 并使用它来查找有关您的日期的信息,而无需使用复杂的慢查询。 这是我的经验,希望对您有所帮助。


我还在下面的链接中搜索并为您找到了一张不错的表格。它是一个 xlsx 文件,附在文章末尾。下载并导入您的数据库,然后将其与以下代码一起使用。
Date Dimension File


我使用的代码是这样的:

WITH X AS (
SELECT
--- The Number You Want ----
ROW_NUMBER() OVER (PARTITION BY YearMonthNum,DayName ORDER BY DateNum) AS DayWeekNumber 
    ,YearMonthNum
    ,DayName
    ,Date
    ,DateNum
    ,MonthNum
    ,DayNumOfWeek
    ,Year
FROM dbo.dimDate Dim --- The Excel I imported
) 
SELECT DISTINCT * 
FROM X X1
JOIN dbo.MyTable T1 -- My Table And my Date Column
    ON T1.myDate = X1.Date
JOIN X X2 ON X2.Year = X1.Year-1   -- I wanted last year match so (-1). use (-n) for n years ago  
            AND X2.MonthNum = X1.MonthNum
            AND X2.DayNumOfWeek = X1.DayNumOfWeek
            AND X2.DayWeekNumber = X1.DayWeekNumber

Here Is Result Image

答案 1 :(得分:0)

这个问题的答案并不容易。它很可能需要一个查找表,提供一些年份的每个月第一天的工作日。从那里可以开发剩余的计算。

从这个意义上说,这篇文章不是一个“答案”,而是一个更长的评论,需要一些格式和一个用于说明的片段。

在使用 JavaScript 时,我发现了一种相当直接的方法来进行这种给定年份和月份的第 n 个工作日计算(这可用于计算合适的查找表)您的数据库):

function createDate2(a){ // [2020,3,1,3] = [year,month,weekday, n-th occurence of weekday in month]
   const d=new Date(a[0],a[1],1); // create first day of the month
   d.setDate((a[2]-d.getDay()-6)%7 + a[3]*7);  // adjust to a[3]-th occurrence of the given weekday a[2]
   return d
 }
// weekday numbering: 0-Sunday, 1-Monday, 2-Tuesday ... 6-Saturday
// extend the Date prototype:
Date.prototype.getDate2=function(){ return [this.getFullYear(),this.getMonth(),this.getDay(),-~(this.getDate()/7)]; } // returns an array: [year,month,weekday, n-th occurence of weekday in month]

// calculate the third Thursday in each month for 2023:
for (let d,m=0;m<12;m++) 
  console.log(createDate2([2023,m,4,3])
              .toLocaleDateString("en-US",{weekday:'long',year:'numeric',month:'long',day:'numeric'})
             );

也许它对某人仍然有用? ... 例如,提取其中的某些部分以获得基于 SQL 的答案?