SQL 日期逻辑 - 查找之前的*非标准*季度

SQL date logic - finding prior *non-standard* quarter

SQL 服务器 2012。

我们有一个使用非标准季度报告的业务部门。季度从 11 月开始,到 10 月结束。为了强调这一点,Q1:11 月到 1 月; Q2:二月到四月; Q3:5-7月; Q4:8月至10月

我正在尝试创建一个“简单而高效”的查询,它可以根据这个非标准方案获取给定日期和 return 上一个“季度”的第一个和最后一个日期。

一位前同事使用非常笨拙的复杂 case 表达式处理了这个问题,我想找到更好的方法。

我知道 SQL 服务器有一些处理季度的内置日期逻辑,但仅限于标准日历季度。因此,以下将可靠地 return 上一季度的第一天,但​​只是从 1 月开始到 12 月结束的季度标准方案...

SELECT DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()) - 1, 0) 
--Shows first day of prior quarter, but only for 'standard' quarters

然后我天真地以为只要减去两个月就可以了,但是有 2/3 的时候这是错误的

SELECT DATEADD(month, -2, DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()) - 1, 0))
--Works for 1/3 dates

从那时起,我尝试了各种嵌套计算方案,但没有任何效果。

任何人都可以帮助我进行此计算 - 或者您会建议我只创建一个日期 table 让我查找非标准季度吗?谢谢

您可以使用以下查询:-

    DECLARE @mydate DATETIME ='2020-04-04'
    SELECT 
     CASE
            WHEN MONTH(@mydate) BETWEEN 2  AND 4  THEN  CAST(YEAR(@mydate) - 1 as varchar)+'-11-01'
            WHEN MONTH(@mydate) BETWEEN 5  AND 7  THEN  CAST(YEAR(@mydate) as varchar)+'-02-01' 
            WHEN MONTH(@mydate) BETWEEN 8 AND 10  THEN  CAST(YEAR(@mydate) as varchar)+'-05-01'
            WHEN MONTH(@mydate) in(11,12)       THEN  CAST(YEAR(@mydate) as varchar)+'-08-01'
            WHEN MONTH(@mydate)=1     THEN  CAST(YEAR(@mydate) -1 as varchar)+'-08-01'
     END AS Start_date,
     CASE
            WHEN MONTH(@mydate) BETWEEN 2  AND 4  THEN  CAST(YEAR(@mydate) as varchar)+'-01-31'
            WHEN MONTH(@mydate) BETWEEN 5  AND 7  THEN  CAST(YEAR(@mydate) as varchar)+'-04-30' 
            WHEN MONTH(@mydate) BETWEEN 8 AND 10  THEN  CAST(YEAR(@mydate) as varchar)+'-07-31'
            WHEN MONTH(@mydate) in(11,12)       THEN  CAST(YEAR(@mydate) as varchar)+'-10-31'
            WHEN MONTH(@mydate)=1     THEN  CAST(YEAR(@mydate) -1 as varchar)+'-10-31'
      END AS End_date

您可以根据需要使用以下查询来确定上一季度的第一个和最后一个日期:

declare @date date = getdate()
select case 
            when MONTH(@date) in (11,12,1) then  datefromparts(year(@date),8,1)
            when MONTH(@date) in (8,9,10)  then  datefromparts(year(@date),5,1)
            when MONTH(@date) in (5,6,7)   then  datefromparts(year(@date),2,1)
            when MONTH(@date) in (2,3,4)   then  datefromparts(year(@date),11,1)
       end StartOfPreviousQuarter,
       case 
            when MONTH(@date) in (11,12,1) then  datefromparts(year(@date),8,30)
            when MONTH(@date) in (8,9,10)  then  datefromparts(year(@date),5,31)
            when MONTH(@date) in (5,6,7)   then  
            CASE WHEN ISDATE(CAST(year(@date) AS char(4)) + '0229') = 1 THEN  datefromparts(year(@date),2,29) ELSE datefromparts(year(@date),2,28) END
            when MONTH(@date) in (2,3,4)   then  datefromparts(year(@date),11,30)
       end EndOfPreviousQuarter

我会加上两个月,取季度的第一天,然后减去两个月:

SELECT DATEADD(month, -2,
               DATEADD(quarter,
                       DATEDIFF(quarter, 0, DATEADD(month, 2, GETDATE())
                               ) - 1, 0
                       )
              ) as Special_Quarter_Date

我更倾向于使用 DATEFROMPARTS():

来写
select dateadd(month, -2,
               datefromparts( year(dateadd(month, 2, getdate()),
                              datepart(quarter, dateadd(month, 2, getdate()) * 3 - 2
                              1
                            )
               )

但逻辑完全一样:加两个月,计算季度,减去两个月。