【问题标题】:Split date range into one row per month in SQL Server pt2在 SQL Server pt2 中每月将日期范围拆分为一行
【发布时间】:2016-04-03 12:47:29
【问题描述】:

这个问题与这篇文章有关:Split date range into one row per month in sql server

但我是 Stackoverflow 的新手,不允许新用户将 cmets 置于提供的解决方案中。这就是为什么我现在将其添加为新问题。

问题是这样的:

我有一个包含两列的表,分别称为“from_date”和“to_date”

表格如下所示:

Table (I am not allowed to embed my picture here, so please click the link)

我想要这样的结果:-

从_日期 ||到日期
------------ ------------

2013-11-25 || 2013-11-30

2013-12-01 || 2013-12-05

该日期从 2013-11-25 拆分为 2013-11-30,另一个日期从 2013-12-01 拆分为 2013-12-05... 可以这样拆分吗?

Aaron Bertrand 的解决方案是这样的:

DECLARE @d TABLE(from_date DATE, to_date DATE);

INSERT @d VALUES ('2013-11-25','2013-12-05');

;WITH n(n) AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY [object_id])-1 
    FROM sys.all_columns
),
d(n,f,t,md,bp,ep) AS 
(
    SELECT n.n, d.from_date, d.to_date, 
           DATEDIFF(MONTH, d.from_date, d.to_date),
           DATEADD(MONTH, n.n, DATEADD(DAY, 1-DAY(from_date), from_date)),
           DATEADD(MONTH, n.n+1, DATEADD(DAY, 0-DAY(from_date), from_date))
    FROM n 
    INNER JOIN @d AS d ON d.to_date >= DATEADD(MONTH, n.n-1, d.from_date)
)
SELECT original_from_date = f, original_to_date = t, 
       new_from_date = CASE n WHEN 0  THEN f ELSE bp END,
       new_to_date   = CASE n WHEN md THEN t ELSE ep END 
FROM d 
WHERE md >= n
ORDER BY original_from_date, new_from_date;

结果:

original_from_date   original_to_date   new_from_date   new_to_date
------------------   ----------------   -------------   -----------
2013-11-25           2013-12-05         2013-11-25      2013-11-30
2013-11-25           2013-12-05         2013-12-01      2013-12-05

Aaron Bertrand 的回答是一个超级强大的查询,但它似乎只适用于 startdate 是在一个月后的一个月内,一个月内有 31 天。例如,如果将 startdate 更改为 2013-5-25(4 月之后,只有 30 天),new_to_date 值不正确:所有整月突然变为最多 30 天:

original_from_date  original_to_date    new_from_date   new_to_date
2013-05-25          2013-12-05          2013-05-25      2013-05-30
2013-05-25          2013-12-05          2013-06-01      2013-06-30
2013-05-25          2013-12-05          2013-07-01      2013-07-30
2013-05-25          2013-12-05          2013-08-01      2013-08-30
2013-05-25          2013-12-05          2013-09-01      2013-09-30
2013-05-25          2013-12-05          2013-10-01      2013-10-30
2013-05-25          2013-12-05          2013-11-01      2013-11-30
2013-05-25          2013-12-05          2013-12-01      2013-12-05

无论开始日期在哪个月份,任何人都可以编辑查询以确保结束日期正确(28、30、31 天和 2 月 29 日闰)?我不知道该怎么做。

非常感谢,Martijn Vermunt

【问题讨论】:

  • 欢迎来到 SO。请阅读How to Ask 并发布完整的问题。仅仅参考其他问题是没有帮助的。
  • 谢谢阿米特。我完全同意:我希望我可以对原始帖子发表评论,这样确实会更容易
  • 所以编辑这个问题并将所有细节都放在这里
  • 好的。现在包括完整的原始问题和解决方案。谢谢
  • 对于非 31 天月的问题,我们深表歉意。 I've fixed my query,因此,如果它在所有情况下都能为您解决问题,那么这个问题可能会作为重复而关闭。

标签: sql-server date-range


【解决方案1】:

已提供答案,已对查询进行编辑和完善。谢谢@Aaron Bertrand 用于更新查询!

DECLARE @d TABLE(from_date DATE, to_date DATE);

INSERT @d VALUES ('2013-11-25','2013-12-05');

;WITH n(n) AS 
(
SELECT ROW_NUMBER() OVER (ORDER BY [object_id])-1 FROM sys.all_columns
),
d(n,f,t,md,bp,ep) AS  
(
SELECT n.n, d.from_date, d.to_date, 
DATEDIFF(MONTH, d.from_date, d.to_date),
DATEADD(MONTH, n.n, DATEADD(DAY, 1-DAY(from_date), from_date)),
DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, n.n, 
 DATEADD(DAY, 1-DAY(from_date), from_date))))
FROM n INNER JOIN @d AS d 
ON d.to_date >= DATEADD(MONTH, n.n-1, d.from_date)
)
SELECT original_from_date = f, original_to_date = t, 
new_from_date = CASE n WHEN 0  THEN f ELSE bp END,
new_to_date   = CASE n WHEN md THEN t ELSE ep END 
FROM d WHERE md >= n
ORDER BY original_from_date, new_from_date;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    相关资源
    最近更新 更多