我如何在SQL中获得周期性月份的最后一天?

发布于 2025-01-18 09:44:46 字数 1233 浏览 2 评论 0 原文

我将根据我写的查询中给出的价值准备接下来的5个月。

 DECLARE @StartDate DATETIME = '2022-03-31', @monthadd INT = 5;
 ; WITH dates AS (
 
   SELECT @StartDate [vade]
   UNION ALL
   SELECT DATEADD(MONTH,1,[vade])
   FROM  dates
   WHERE DATEADD(MONTH,1,[vade]) <= DATEADD(MONTH,@monthadd,@StartDate)
 )
 SELECT * 
 FROM  dates 
 OPTION (MAXRECURSION 0)
 GO

但是,当一个月的最后一天为31时,有必要在接下来的几个月中列出最后一天,即最近的一天。我该怎么做?

Actual results

vade
2022-03-31 00:00:00.000
2022-04-30 00:00:00.000
2022-05-30 00:00:00.000
2022-06-30 00:00:00.000
2022-07-30 00:00:00.000
2022-08-30 00:00:00.000

编辑:

这是一个成熟计划。如果该人在本月的31日分期付款,则必须在每个月的最后一天进行付款。如果他在30日这样做,那么如果有30天,如果有30天,则应该有30天,如果有29天,则应有29天。如果到20开始,则必须是每个月的20个。想象一下,您在本月30日贷款。如果月份为29天,他们将要求您在第29天付款,如果月份为31天,他们会要求您在第30天付款。我知道这很困惑,对此我感到抱歉。

I am preparing the next 5 months date according to the value given in the query I wrote.

 DECLARE @StartDate DATETIME = '2022-03-31', @monthadd INT = 5;
 ; WITH dates AS (
 
   SELECT @StartDate [vade]
   UNION ALL
   SELECT DATEADD(MONTH,1,[vade])
   FROM  dates
   WHERE DATEADD(MONTH,1,[vade]) <= DATEADD(MONTH,@monthadd,@StartDate)
 )
 SELECT * 
 FROM  dates 
 OPTION (MAXRECURSION 0)
 GO

However, when the last day of the month is 31, it is necessary to list the last day, which is the nearest day, in the following months. how do i do this?

Actual results

vade
2022-03-31 00:00:00.000
2022-04-30 00:00:00.000
2022-05-30 00:00:00.000
2022-06-30 00:00:00.000
2022-07-30 00:00:00.000
2022-08-30 00:00:00.000

Edit:

This is a maturity plan. If the person makes installments on the 31st of the month, the payment must be made on the last day of each month. If he does it on the 30th, the month should have 30 if it has 30 days, 30 if it has 31 days, and 29 if it has 29 days. If maturity starts on the 20th, it must be the 20th of each month. Imagine you take out a loan on the 30th of the month. If the month is 29 days, they will ask you to pay on the 29th day, and if the month is 31 days, they will ask you to pay on the 30th day. I know it's very confusing and I'm sorry about that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把昨日还给我 2025-01-25 09:44:46

更新了2022-04-01

如果我正确理解,您想为每个月返回相同的“一天” - @startdate是@startdate是最后一天月。

一种方法是确定@startdate是否是该月的最后一天。如果是这样,请使用 eomonth()在随后的每个月中返回最后一天。否则,请使用dateadd()每月返回指定的“天”。这种方法应适用于任何日期。

一种方法如下:

  1. 如果成熟日期是一个月的最后一天,或者 day of of月是&gt;随后一个月的天数,使用 eomonth()要返回该月的最后一天
  2. ,否则使用dateadd()和 datefromparts()使用成熟 day day day

sql:

-- Note: Using 12 months for demo only
; WITH dates AS (
  SELECT @StartDate AS MaturityDate
         , IIF(@StartDate = EOMONTH(@StartDate), 1, 0) AS IsEOM
  UNION ALL
  SELECT 
         CASE -- Maturity date is last day of month OR 
              -- Maturity "day" is > number of days in current month
              WHEN IsEOM = 1 OR DAY(@StartDate) > DAY( EOMONTH(NextMaturityDate) ) 
                    THEN EOMONTH( DATEADD(MONTH, 1, MaturityDate ))
              -- Otherwise, maturity "day" is valid for current month
              ELSE DATEFROMPARTS(
                         Year(NextMaturityDate)
                         , Month(NextMaturityDate)
                         , DAY(@StartDate)
                      )
         END
         , IsEOM
  FROM  ( SELECT MaturityDate
                 , IsEOM
                 , DATEADD(MONTH, 1, MaturityDate) AS NextMaturityDate
          FROM  dates
        ) t
  WHERE MaturityDate < @EndDate
)
SELECT MaturityDate AS [vade] 
FROM   dates 
OPTION (MAXRECURSION 0)

2022-03-31 (一个月的最后一天)

vade
2022-03-03-31
2022-04-30
2022- 05-31
2022-06-30
2022-07-31
2022-08-31
2022-09-09-30
2022-10-31 2022-11-11-11-30
2022-12-12-31
2023-01-01-31
2023-31 2023-02-28
2023-2023-2023--02-28
2023- 03-31
2023-04-30
2023-05-31
2023-06-30

2022-03-03-30的结果 (不是最后一天)

vade
2022-03-30
2022-04-30
2022-05-05-30
2022-06-06-30
2022-07-07-07-30
2022-08-30
2022-09-09-09-30
2022-10-30 2022-10
2022-11-11-30
20222222222222222222222222222222222-30 202222222222222222222年-12-30
2023-01-30
2023-02-28
2023-03-03-30
2023-04-30
2023-05-30
2023-06-06-30

db&lt; /dbfiddle.uk/?rdbms = sqlServer_2019& fiddle = de5de5da8fe22e53300854d4ad888102f314“ rel =“ nofollow noreferrer”>在这里

Updated 2022-04-01

If I'm understanding correctly, you want to return the same "day" for each month - except when @StartDate is the last day of the month.

One approach would be to determine if the @StartDate is the last day of the month. If so, use EOMONTH() to return the last day in each of the subsequent months. Otherwise, use DATEADD() to return the specified "day" in each month. This approach should work for any date.

One approach is as follows:

  1. If Maturity Date is last day of month, OR Maturity Day of month is > number of days in subsequent month, use EOMONTH() to return the last day of that month
  2. Otherwise, use DATEADD() and DATEFROMPARTS() to generate the next date using the Maturity Day of month

SQL:

-- Note: Using 12 months for demo only
; WITH dates AS (
  SELECT @StartDate AS MaturityDate
         , IIF(@StartDate = EOMONTH(@StartDate), 1, 0) AS IsEOM
  UNION ALL
  SELECT 
         CASE -- Maturity date is last day of month OR 
              -- Maturity "day" is > number of days in current month
              WHEN IsEOM = 1 OR DAY(@StartDate) > DAY( EOMONTH(NextMaturityDate) ) 
                    THEN EOMONTH( DATEADD(MONTH, 1, MaturityDate ))
              -- Otherwise, maturity "day" is valid for current month
              ELSE DATEFROMPARTS(
                         Year(NextMaturityDate)
                         , Month(NextMaturityDate)
                         , DAY(@StartDate)
                      )
         END
         , IsEOM
  FROM  ( SELECT MaturityDate
                 , IsEOM
                 , DATEADD(MONTH, 1, MaturityDate) AS NextMaturityDate
          FROM  dates
        ) t
  WHERE MaturityDate < @EndDate
)
SELECT MaturityDate AS [vade] 
FROM   dates 
OPTION (MAXRECURSION 0)

Results for 2022-03-31 (Last Day Of Month)

vade
2022-03-31
2022-04-30
2022-05-31
2022-06-30
2022-07-31
2022-08-31
2022-09-30
2022-10-31
2022-11-30
2022-12-31
2023-01-31
2023-02-28
2023-03-31
2023-04-30
2023-05-31
2023-06-30

Results for 2022-03-30 (NOT Last Day Of Month)

vade
2022-03-30
2022-04-30
2022-05-30
2022-06-30
2022-07-30
2022-08-30
2022-09-30
2022-10-30
2022-11-30
2022-12-30
2023-01-30
2023-02-28
2023-03-30
2023-04-30
2023-05-30
2023-06-30

db<>fiddle here

第七度阳光i 2025-01-25 09:44:46

/code>函数已经考虑了角案例,例如本月底,因此您无需处理。

为了拥有一个清洁代码,您可以放下 <<代码>存储过程 ,创建(或替换) dates_list 表,然后在添加到开始日期的几个月中循环。

DELIMITER //

CREATE OR REPLACE PROCEDURE create_dates_list (
    IN start_date DATETIME, 
    IN num_months INT
)
BEGIN
    DECLARE idx INT DEFAULT 0;

    CREATE OR REPLACE TABLE dates_list (
        date DATE
    );

    WHILE idx <> num_months DO
        INSERT INTO tab VALUES(
            DATEADD(@start_date, INTERVAL @idx MONTH)
        );
        SET idx = idx + 1;
    END WHILE;
END //

DELIMITER ;

当您需要获得新的日期时,您可以通过设置参数并调用存储过程来刷新该表:

DECLARE @StartDate DATETIME = '2022-03-31', @monthadd INT = 5;

CALL create_dates_list(@StartDate, @monthadd);

您可以随时使用SQL赋予您的工具随时自由访问该表。

如果您不需要表格以进行更多会话,则可以将表定义为临时官方文档>详细且全面的示例,请查看以了解更多信息。

The DATEADD function already takes into account of the corner cases, like the end of the month, so you don't need to handle it.

In order to have a cleaner code, you can lay down a stored procedure, that creates (or replaces) a dates_list table and then cycles over the number of months to add to the start date.

DELIMITER //

CREATE OR REPLACE PROCEDURE create_dates_list (
    IN start_date DATETIME, 
    IN num_months INT
)
BEGIN
    DECLARE idx INT DEFAULT 0;

    CREATE OR REPLACE TABLE dates_list (
        date DATE
    );

    WHILE idx <> num_months DO
        INSERT INTO tab VALUES(
            DATEADD(@start_date, INTERVAL @idx MONTH)
        );
        SET idx = idx + 1;
    END WHILE;
END //

DELIMITER ;

When you need to obtain new dates, you can refresh that table by setting the parameters and calling the stored procedure:

DECLARE @StartDate DATETIME = '2022-03-31', @monthadd INT = 5;

CALL create_dates_list(@StartDate, @monthadd);

You can freely access the table anytime by using the tools that sql empowers you with.

If you don't need the table to exist for further sessions, you can define the table as TEMPORARY. The official documentation on temporary tables is very detailed and comprehensive of examples, check it out to get to know more about it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文