【问题标题】:Billing Cycle Date Range计费周期日期范围
【发布时间】:2018-06-13 14:42:02
【问题描述】:

代码:

DECLARE @CurrentDate DATE = '2018-01-02' ;  -- Can be any date. This is just a date I used as an anchor point.
DECLARE @BillingDayOfMonth INT = 31 ;       -- The day of the billing every month (can be between 1st and 31st of the month).

;WITH [TT1] ( [N] ) AS
    (
        SELECT  1
        UNION ALL
        SELECT  1
    )
    , [TT2] ( [N] ) AS
    (
        SELECT  1
        UNION ALL
        SELECT  1
        UNION ALL
        SELECT  1
        UNION ALL
        SELECT  1
        UNION ALL
        SELECT  1
        UNION ALL
        SELECT  1
    )
    , [TT] ( [N] ) AS
    (
        SELECT      ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL ) )
        FROM        [TT1] [T1]
        CROSS JOIN  [TT2] [T2]
    )
SELECT  [N]
FROM    [TT] ; -- This gives me the count of 12 cycles (can vary).

目标: 返回当前和 X 个以前的计费周期日期(上例中总共 12 个周期)。

如果一个月内不存在 BillingDayOfMonth(即 29 日至 31 日,具体取决于月份),请选择该月的最后一天作为 BillingDayOfMonth。因此,如果 BillingDayOfMonth = 31st,则这一天在 11 月不存在。因此周期将在 @11/30 而不是 11/31 开始。上面的代码不完整,需要您帮助找出有效的解决方案。谢谢

期望的输出:

CycleStartDate  CycleEndDate
2017-12-31      2018-01-30      -- The most current cycle
2017-11-30      2017-12-30
2017-10-31      2017-11-29
2017-09-30      2017-10-30
2017-08-31      2017-09-29
2017-07-31      2017-08-30
2017-06-30      2017-07-30
2017-05-31      2017-06-29
2017-04-30      2017-05-30      -- Notice the EndDate
2017-03-31      2017-04-29      -- Notice the EndDate
2017-02-28      2017-03-30      -- Notice the StartDate
2017-01-31      2017-02-27      -- Notice the EndDate

【问题讨论】:

    标签: sql sql-server tsql date sql-server-2012


    【解决方案1】:

    因此,根据您的数字表方法和规则,您可以使用如下查询。

    我针对 @BillingDayOfMonth 的值(例如 25、28、30)进行了测试,发现结果相当正确。

    See live demo

    DECLARE @CurrentDate DATE = '2018-01-02' ;  -- Can be any date. This is just a date I used as an anchor point.
    DECLARE @BillingDayOfMonth INT = 31 ;       -- The day of the billing every month (can be between 1st and 31st of the month).
    DECLARE @StartDate DATE
    SET @StartDate=   CASE WHEN 
                           DAY(EOMONTH(@CurrentDate)) < @BillingDayOfMonth
                           THEN
                           EOMONTH(@CurrentDate)
                           ELSE
                           DATEFROMPARTS(YEAR(@CurrentDate),MONTH(@CurrentDate),@BillingDayOfMonth)
                       END
    
    ;WITH [TT1] ( [N] ) AS
        (
            SELECT  1
            UNION ALL
            SELECT  1
        )
        , [TT2] ( [N] ) AS
        (
            SELECT  1
            UNION ALL
            SELECT  1
            UNION ALL
            SELECT  1
            UNION ALL
            SELECT  1
            UNION ALL
            SELECT  1
            UNION ALL
            SELECT  1
        )
        , [TT] ( [N] ) AS
        (
            SELECT    
            ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL ) )
    
            FROM        [TT1] [T1]
            CROSS JOIN  [TT2] [T2]
        )
    
    SELECT  CycleStartDate  = 
                        DATEADD(M,-N,@StartDate)
            ,
            CycleEndDate    =
                        DATEADD(D,-1,DATEADD(M,1-N,@StartDate))
    
    FROM    [TT] ;
    

    【讨论】:

    • 这是一个巧妙的解决方案。谢谢。不过只有一件事。当 CurrentDate = '2018-01-02' AND BillingDayOfMonth 为 01(昨天开始新周期)或 02(今天开始新周期)时,我们可以将 '2018-01-01' 设为 '2018-01-31'(对于01) '2018-01-02' TO '2018-02-01' (for 02) 作为最新结果?基本上,在“2018-01-02”,您已经处于“01/01”或(“01/02”)到“01/31”(或“02/1”)周期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多