我正面临这个问题,今天花了很多时间。所以,我想在这里分享它:
我有一个存储 debitDate 的表,并且有一个存储过程,每个月我们在表中将借记日期设置为下个月。
因此,如果其借记日期为29th Jan, 2020 -> 29th Feb, 2020 -> 29th March, 2020
-则应这样进行。我正在存储过程中使用DATEADD()函数。
但是在30日和31日,我面临问题。在未来的几年中,它应该像下面这样工作:
期望的行为:
30th Jan, 2020 -> 29th Feb, 2020 -> 30th Mar, 2020 -> 30th Apr, 2020
30th Jan, 2021 -> 28th Feb, 2021 -> 30th Mar, 2021 -> 30th Apr, 2021
31st Jan, 2020 -> 29th Feb, 2020 -> 31st Mar, 2020 -> 30th Apr, 2020
问题:
30th Jan, 2020 -> 29th Feb, 2020 -> 29th Mar, 2020 -> 29th Apr, 2020
30th Jan, 2021 -> 28th Feb, 2021 -> 28th Mar, 2021 -> 28th Apr, 2021
31st Jan, 2020 -> 29th Feb, 2020 -> 29th Mar, 2020 -> 29th Apr, 2020
答案 0 :(得分:1)
解决方案1 :
对于解决方案,我认为我可以在表中添加一个新列作为 previousDebitDate ,并且当我们更新借记日期时,我们将检查上一个DebitDate日是30还是31。 如果为true,则
DATEADD(MONTH, 2, @previousDebitDate)
其他
DATEADD(MONTH, 1, @debitDate)
如果有人有更好的解决方案,请随时发布您的答案。
解决方案2 :
对于此问题,更好的解决方案是将 debitDay 作为新列添加到表中,并仅保存日部分(例如30)并即时计算每个月的借记日期。
我认为解决方案2更好!谢谢@Arvo !!!
答案 1 :(得分:0)
也许我已经非常了解,也许不是,但是这就是我在寻找的东西
CREATE TABLE Data
(
Dates DATE
);
INSERT Data(Dates) VALUES
('2020-01-30');
WITH CTE AS
(
SELECT Dates,
DATEADD(Month, 1, Dates) NextMonth,
DAY(EOMONTH(DATEADD(Month, 1, Dates))) LastDay
FROM Data
UNION ALL
SELECT DATEADD(Month, 1, Dates),
DATEADD(Month, 1, NextMonth),
DAY(EOMONTH(DATEADD(Month, 1, NextMonth)))
FROM CTE
WHERE Dates <= '2021-12-31'
)
SELECT Dates, NextMonth, DATEFROMPARTS(YEAR(Dates), MONTH(NextMonth),
CASE WHEN LastDay > 30 THEN 30 ELSE LastDay END) Value
FROM CTE;
哪个会返回:
+------------+------------+------------+
| Dates | NextMonth | Value |
+------------+------------+------------+
| 2020-01-30 | 2020-02-29 | 2020-02-29 |
| 2020-02-29 | 2020-03-29 | 2020-03-30 |
| 2020-03-29 | 2020-04-29 | 2020-04-30 |
| 2020-04-29 | 2020-05-29 | 2020-05-30 |
| 2020-05-29 | 2020-06-29 | 2020-06-30 |
| 2020-06-29 | 2020-07-29 | 2020-07-30 |
| 2020-07-29 | 2020-08-29 | 2020-08-30 |
| 2020-08-29 | 2020-09-29 | 2020-09-30 |
| 2020-09-29 | 2020-10-29 | 2020-10-30 |
| 2020-10-29 | 2020-11-29 | 2020-11-30 |
| 2020-11-29 | 2020-12-29 | 2020-12-30 |
| 2020-12-29 | 2021-01-29 | 2020-01-30 |
| 2021-01-29 | 2021-02-28 | 2021-02-28 |
| 2021-02-28 | 2021-03-28 | 2021-03-30 |
| 2021-03-28 | 2021-04-28 | 2021-04-30 |
| 2021-04-28 | 2021-05-28 | 2021-05-30 |
| 2021-05-28 | 2021-06-28 | 2021-06-30 |
| 2021-06-28 | 2021-07-28 | 2021-07-30 |
| 2021-07-28 | 2021-08-28 | 2021-08-30 |
| 2021-08-28 | 2021-09-28 | 2021-09-30 |
| 2021-09-28 | 2021-10-28 | 2021-10-30 |
| 2021-10-28 | 2021-11-28 | 2021-11-30 |
| 2021-11-28 | 2021-12-28 | 2021-12-30 |
| 2021-12-28 | 2022-01-28 | 2021-01-30 |
| 2022-01-28 | 2022-02-28 | 2022-02-28 |
+------------+------------+------------+
好多了
WITH CTE AS
(
SELECT 1 N, Dates, Dates ExpectedValue
FROM Data
UNION ALL
SELECT N+1, DATEADD(Month, 1, Dates), DATEFROMPARTS(YEAR(ExpectedValue), MONTH(DATEADD(Month, 1, ExpectedValue)),
CASE WHEN DAY(EOMONTH(DATEADD(Month, 1, ExpectedValue))) > 30 THEN 30
ELSE DAY(EOMONTH(DATEADD(Month, 1, ExpectedValue)))
END)
FROM CTE
WHERE N < 15
)
SELECT *
FROM CTE
ORDER BY N;
返回:
+----+------------+---------------+
| N | Dates | ExpectedValue |
+----+------------+---------------+
| 1 | 2020-01-30 | 2020-01-30 |
| 2 | 2020-02-29 | 2020-02-29 |
| 3 | 2020-03-29 | 2020-03-30 |
| 4 | 2020-04-29 | 2020-04-30 |
| 5 | 2020-05-29 | 2020-05-30 |
| 6 | 2020-06-29 | 2020-06-30 |
| 7 | 2020-07-29 | 2020-07-30 |
| 8 | 2020-08-29 | 2020-08-30 |
| 9 | 2020-09-29 | 2020-09-30 |
| 10 | 2020-10-29 | 2020-10-30 |
| 11 | 2020-11-29 | 2020-11-30 |
| 12 | 2020-12-29 | 2020-12-30 |
| 13 | 2021-01-29 | 2020-01-30 |
| 14 | 2021-02-28 | 2020-02-29 |
| 15 | 2021-03-28 | 2020-03-30 |
+----+------------+---------------+
这里是db<>fiddle