SQL 服务器根据开始日期和频率查找日期范围

SQL Server Find the Date Range based on Start Date and Frequence

我正在尝试创建一个函数,我可以在其中指定任何日期,它可以 return 特定资产的计费日期范围。

例如 下面我有一个 AssetBilling table 的示例,它告诉我应该根据开始日期对资产进行计费的频率。

如果我给函数一个日期:资产 Red Car25/02/2021 它应该告诉我它所属的计费周期是:从 01/02/202101/03/2021

我试过跟随 CTE,但我不完全确定如何使用它,因为我以前没有做过:

DECLARE @InvDate AS DATE = '25/02/2021',
        @ID AS INT = 1 -- Red Car example
;WITH CTE AS (
    SELECT StartDate, DATEADD(MM, Frequency, StartDate) EndDate 
    FROM AssetBilling WHERE ID = @ID
    UNION ALL
    SELECT DATEADD(MM, 1, StartDate), DATEADD(MM, 1, EndDate)
    FROM CTE 
    WHERE
    StartDate >= @InvDate AND EndDate <= @InvDate 
)
SELECT *
FROM 
CTE

这是我得到的结果:

CREATE TABLE [dbo].[AssetBilling](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Asset] [varchar] (150) NULL,
    [StartDate] [date] NULL,
    [Frequency] [int] NULL,
    [BillType][varchar](50)NULL
);

INSERT INTO AssetBilling
(Asset, StartDate, Frequency, BillType)
VALUES
('Red Car', '01/01/2021', 1, 'Monthly'),
('Blue Car', '25/05/2021', 3, 'Quarterly')

我认为您在这里不需要递归 CTE,但对于 Larnu 的观点,请说明当频率不是每月一次时您希望发生什么(修改此查询以支持我需要准确理解您的内容例如,当它是季度时,并且提供的 InvDate 是在该期间的第 2 个月或第 3 个月。

DECLARE @InvDate date = '20210225', -- avoid regional, ambiguous formats
        @ID      int  = 1;

;WITH src(StartDate, Frequency) AS 
(
  SELECT DATEADD(MONTH, 
    DATEDIFF(MONTH, StartDate, @InvDate), StartDate), Frequency
  FROM dbo.AssetBilling -- always use schema prefix
  WHERE ID = @ID
)
SELECT StartDate, EndDate = DATEADD(MONTH,Frequency,StartDate)
  FROM src;

这只是一个猜测,有一个模糊的例子,没有根据要求提供进一步的例子或解释,但也许是这样的:

DECLARE @InvDate date = '20220225',
        @ID int = 1;

SELECT StartDate,
       CASE WHEN @InvDate > EndDate THEN EndDate --I assume you have an end date
            WHEN DATEDIFF(MONTH,StartDate,@InvDate) < Frequency THEN DATEADD(MONTH, Frequency, StartDate)
            WHEN DATEDIFF(MONTH,StartDate,@InvDate) % Frequency != 0 THEN DATEADD(MONTH, ((DATEDIFF(MONTH,StartDate,@InvDate) / Frequency) * Frequency) + Frequency, StartDate)
            ELSE @InvDate
       END
FROM dbo.AssetBilling
WHERE ID = @ID;

db<>fiddle

可能有一些场景我没有在 WHEN 中涵盖,但这很难知道什么时候我们有 1 个示例。也许这给了你足够大的线索。