每个项目的2个日期之间的月份

时间:2017-04-14 16:35:34

标签: sql sql-server tsql

您好我正在尝试运行一个查询,以便为我拥有的每个项目在两个日期之间的每个月返回一行。参见示例数据:

<h1 class="x">
    <span class="y">Here's a header</span>
</h1>
<div class="z">Here's some more text with a different format</div>

需要的最终数据:

Project  Start      End
1        1/1/2015   3/1/2015
2        2/1/2015   4/1/2015

我有几个项目,需要一个查询来同时为所有这些项目执行此操作。我该如何在SQL Server中执行此操作?

4 个答案:

答案 0 :(得分:1)

如果你有或为Months创建一个表,这很简单:

create table dbo.Months([Month] date primary key);
declare @StartDate     date = '20100101'
       ,@NumberOfYears int  = 30;

insert dbo.Months([Month],MonthEnd)
  select top (12*@NumberOfYears) 
      [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate)
  from master.dbo.spt_values;

如果您真的不想拥有Months表,可以像这样使用cte

declare @StartDate     date = '20100101'
       ,@NumberOfYears int  = 10;

;with Months as (
  select top (12*@NumberOfYears) 
    [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate)
  from master.dbo.spt_values
)

然后像这样查询:

select 
    t.Project
  , m.Month
from t
  inner join dbo.Months m
    on m.Month >= t.Start
   and m.Month <= t.[End]

rextester演示:http://rextester.com/SXPX26360

返回:

+---------+------------+
| Project |   Month    |
+---------+------------+
|       1 | 2015-01-01 |
|       1 | 2015-02-01 |
|       1 | 2015-03-01 |
|       2 | 2015-02-01 |
|       2 | 2015-03-01 |
|       2 | 2015-04-01 |
+---------+------------+

日历和数字表参考:

答案 1 :(得分:1)

我个人喜欢这种东西的计数表。这是t-sql的瑞士军刀。

我为此在系统上创建了一个视图。如果您不想创建视图,只要需要计数表,就可以轻松使用这些ctes。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

现在我们只需要在表格中提供您的样本数据。

创建表#Projects (     项目int     ,开始日期时间     ,EndDate datetime )

插入#Projects 选择1,'1/1/2015','3/1/2015'联合所有 选择2,'2/1/2015','4/1/2015'

此时我们在这里找到了真正的问题,即检索您的信息。使用示例数据和视图,这变得非常简单。

select p.*
    , NewMonth = DATEADD(MONTH, t.N - 1, p.Start)
from #Projects p
join cteTally t on t.N <= DATEDIFF(MONTH, p.Start, p.EndDate) + 1
order by p.Project
    , t.N

答案 2 :(得分:1)

另一个选项是带有临时计数表的CROSS APPLY

Select A.Project
      ,Month = B.D
 From  YourTable A
 Cross Apply (
                Select Top (DateDiff(MONTH,A.Start,A.[End])+1) D=DateAdd(Month,-1+Row_Number() Over (Order By(Select null)),A.Start) 
                 From  master..spt_values 
             ) B

返回

Project Month
1       2015-01-01
1       2015-02-01
1       2015-03-01
2       2015-02-01
2       2015-03-01
2       2015-04-01

答案 3 :(得分:0)

生成时间series从链接中获取帮助。

然后在

之间加入时间

选择 - 某事 FROM table1 a / 类型 / JOIN table2 b ON b.field2 BETWEEN a.field2 AND a.field3