2011-06-07 100 views
2

我有一排数据,开始日期和结束日期通常是从月初到月底。然而,有时行有 - 几个月长 - 在一个月的中间开始,结束在同一个月或未来的月份 - 开始于一个月的开始,但结束某处在一个月的中间未来一个月。按月分解日期范围

我需要按月分解这些日期范围,但不知道如何去做这件事。

任何指导表示赞赏。

感谢,

+0

因此,如果开始日期和结束日期是在两个不同的月份,你怎么想代表这个?两个不同的值,每个月一个?只是开始日期?只是结束日期?这两个日期的平均值? – 2011-06-07 18:58:44

+0

我需要通过各自的一个月,以保持每个单独的,所以如果例如它是6月13日至7月18日,那么它应该是 6月13日至6月30日 七月1日至7月18日 例如 – mohsen 2011-06-07 19:16:52

+0

你的问题太锚定在你的上下文中对其他人都有用。它也很模糊。请更改它并提供有关您正在使用的工具,已尝试的内容,示例输入数据和所需输出数据的信息。 – 2011-06-07 21:35:36

回答

1

一个标准关键是要建立一个months表,然后选择所有月份相交的日期范围。

您可以再往前走一步,并在您的选择中使用CASE声明,以便您获取月份的开始日期,该月份是所提供的开始日期和月份的开始日期的最大值,以及结束日期月份是所提供的最低月份和月末的最低月份。

这将让你采取单一的日期范围,并获得一组日期范围。然后,您可以将该查询加入到您月份的数据集和组中,以便在一个月的范围内按月对数据进行分割。 (这个技巧在某些时段可能没有数据时特别有用,但您希望它们显示,只需使用左连接。)

2

您可以使用数字表执行此任务。

在下面称为master..spt_values系统表的示例查询被用作数表的替换:

SELECT 
    CASE WHEN BeginDate > MonthStart THEN BeginDate ELSE MonthStart END AS BeginDate, 
    CASE WHEN EndDate < MonthEnd THEN EndDate ELSE MonthEnd END AS EndDate, 
    … /* other columns as needed */ 
FROM (
    SELECT 
    d.*, /* or you could be more specific here */ 
    (
     DATEADD(month, DATEDIFF(month, 0, d.BeginDate) + v.number, 0) 
    ) AS MonthStart, 
    DATEADD(day, -1, 
     DATEADD(month, DATEDIFF(month, 0, d.BeginDate) + v.number + 1, 0) 
    ) AS MonthEnd 
    FROM RowsOfData d 
    INNER JOIN master..spt_values v ON v.type = 'P' 
     AND v.number BETWEEN 0 AND DATEDIFF(month, d.BeginDate, d.EndDate) 
) s 

每一行都被划分成一系列的行,其中BeginDate或者是实际BeginDate或开始取决于哪个值更大,同样适用于EndDate。为了说明,以下行

BeginDate EndDate 
---------- ---------- 
2010-03-05 2010-03-24 
2010-04-16 2010-05-05 
2010-06-29 2006-08-12 
2010-10-10 2011-02-01 

将拆分这样的:

BeginDate EndDate 
---------- ---------- 
2010-03-05 2010-03-24 
2010-04-16 2010-04-30 
2010-05-01 2010-05-05 
2010-06-29 2010-06-30 
2010-07-01 2010-07-31 
2010-08-01 2010-08-12 
2010-10-10 2010-10-31 
2010-11-01 2010-11-30 
2010-12-01 2010-12-31 
2011-01-01 2011-01-31 
2011-02-01 2011-02-02 
+0

+1为“数字”或顺序方法。 – pilcrow 2011-06-08 16:54:29