【问题标题】:split date range into months将日期范围拆分为月份
【发布时间】:2011-08-28 01:37:10
【问题描述】:

我想将日期范围分成各个月份。
例如 - 我有一个视图,其中包含以下方式的数据:

user project startdate   enddate
-----------------------------------
 A   abc1    2011-01-01  2011-12-31
 A   abc2    2011-01-01  2011-05-01
 B   xyz1    2011-01-01  2011-03-01

我希望上面的数据可以这样显示:

user project startdate   enddate     
 A   abc1    2011-01-01  2011-01-31
 A   abc1    2011-02-01  2011-02-28
 A   abc1    2011-03-01  2011-03-31
 ----------------------------------
 A   abc2    2011-01-01  2011-01-31
 A   abc2    2011-02-01  2011-02-28
 ----------------------------------
 B   xyz1    2011-01-01  2011-01-31
 B   xyz1    2011-02-01  2011-02-28
 B   xyz1    2011-03-01  2011-03-31

有人可以帮我吗?

【问题讨论】:

  • 你试过什么?您知道 SQL 中没有行分隔符,对吧?

标签: sql sql-server sql-server-2005 tsql


【解决方案1】:

以下查询应该可以解决问题。 CTEWITH 子句)动态生成一些我们可以用来加入的月份数据。

declare @test table (
    userid char(1),
    project char(4),
    startdate datetime,
    enddate datetime)

insert into @test
select 'A', 'abc1', '1/1/2011', '12/31/2011'
union select 'A', 'abc2', '1/1/2011', '5/1/2011'
union select 'B', 'xyz1', '1/1/2011', '3/1/2011'

--select * from @test

;with MonthList as (
    select 
        DATEADD(month, M, '12/1/1899') as 'FirstDay',
        dateadd(day, -1, dateadd(month, M + 1, '12/1/1899')) as 'LastDay',
        DATEADD(month, M + 1, '12/1/1899') as 'FirstDayNextMonth'
    from (
        select top 3000 ROW_NUMBER() over (order by s.name) as 'M'
        from master..spt_values s) s
)

select
    t.userid, t.project, ml.FirstDay, ml.LastDay
from
    @test t
    inner join MonthList ml
        on  t.startdate < ml.FirstDayNextMonth
            and t.enddate >= ml.FirstDay

【讨论】:

  • 如果我有时间陪我的约会对象怎么办?当我用日期定义时间时,我尝试了上面的查询,但分成几个月工作错误
【解决方案2】:

这是一个程序,可以满足您的需求。但是,如果您花时间学习 CTE,这是一种更强大的方法(2005 年及以后)。

create procedure dbo.ExpandProjects
as
begin
    DECLARE @UserN CHAR(1) 
    DECLARE @Proj CHAR(4)
    DECLARE @Start  DATETIME
    DECLARE @End    DATETIME
    DECLARE @DtLoop DATETIME
    DECLARE @dtNExt DATETIME

    SET NOCOUNT ON

    CREATE TABLE #ProjList
    (
        userName char(1),
        project  char(4),
        startDate dateTime,
        EndDate DateTime
    )


    DECLARE db_cursor CURSOR FOR  
    SELECT *
    FROM Projects

    OPEN db_cursor   
    FETCH NEXT FROM db_cursor INTO @UserN,@Proj,@Start,@end

    WHILE @@FETCH_STATUS = 0   
    BEGIN   
        SET @DtLoop = STR(MONTH(@Start))+'/01/'+STR(YEAR(@Start))
        WHILE @DtLoop <= @End
        BEGIN
            SET @dtNext = DATEADD(m,1,@dtLoop)

            INSERT INTO #ProjList 
                        VALUES(@UserN,@Proj,@DtLoop,DateAdd(d,-1,@dtNExt))
            SET @DtLoop = @dtNext


        END

        PRINT @DtLoop

        FETCH NEXT FROM db_cursor INTO @UserN,@Proj,@Start,@end
    END   

    CLOSE db_cursor   
    DEALLOCATE db_cursor

    SELECT * FROM #ProjList ORDER BY 1,2



end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多