我想将日期范围分成几个月 例如 - 我有一个视图,其中包含以下方式的数据:
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
有人可以帮我吗?
答案 0 :(得分:4)
以下查询应该可以解决问题。 CTE
(WITH
子句)动态生成一些我们可以用来加入的Month数据。
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
答案 1 :(得分:0)
这是一个为您提供所需内容的程序。但是,如果你花时间学习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