根据日期差异从单行生成多行

时间:2014-08-12 10:49:11

标签: tsql sql-server-2008-r2

我想从1行生成多行,具体取决于dtStart和dtEnd中的日期差异

-- This is demo table to show the issue 
create table #temp(Id int,hTenant int , dtStart datetime,dtEnd datetime)

Insert into #temp values(1,8,'2013-01-08 00:00:00.000','2014-01-01 00:00:00.000')

数据应该通过查询返回: -

**Id**  **Tenant**  **Month**                   **Year**
 1        8          Aug                        2013
 1        8          Sep                        2013
 1        8          Oct                        2013
 1        8          Nov                        2013
 1        8          Dec                        2013
 1        8          Jan                        2014

我如何实现这一目标

我创建了一个表值函数,该函数返回月份和年份,但无法将其与表格连接以获取ID和租户

Create FUNCTION vw_emg_common_GetYearMonthDiffList ( @startdt datetime,@enddt datetime )
RETURNS @Months TABLE
(
Months     int,
Years int,
StartDate datetime,
EndDate datetime
 )
AS
BEGIN
    WHILE (@startdt< @enddt) 
    BEGIN

    INSERT INTO @Months(Months,Years,StartDate,EndDate) VALUES                           (MONTH(@startdt),Year(@startdt),@startdt,@enddt)
    SET  @startdt = DATEADD(MONTH,1,@startdt)
  end
         INSERT @Months
            Select  Months,Years,StartDate,EndDate from @Months 

   RETURN
    end

函数调用: -

  select *   FROM vw_emg_common_GetYearMonthDiffList('2013-01-01             00:00:00.000','2013-12-01 00:00:00.000' )

2 个答案:

答案 0 :(得分:1)

使用Cross JoinCTE尝试此方法。您可能需要创建一个函数(或稍微修改)。 Fiddle demo is here

DECLARE @sd DATE = '20130801', @ed DATE = '20140101',
        @id INT = 1, @hTenant INT = 8

;WITH CTE AS
(
    SELECT DATEDIFF(MONTH, @sd,  @ed) Months
)
SELECT DISTINCT @id Id, @hTenant Tenant, 
       DATENAME(MONTH, DATEADD(MONTH, number, @sd)) [Month], 
       YEAR(DATEADD(MONTH, number, @sd)) [Year] 
FROM master..spt_values x
            CROSS JOIN CTE
WHERE x.number BETWEEN 0 AND Months

结果

| ID | TENANT |     MONTH | YEAR |
|----|--------|-----------|------|
|  1 |      8 |    August | 2013 |
|  1 |      8 | September | 2013 |
|  1 |      8 |   October | 2013 |
|  1 |      8 |  November | 2013 |
|  1 |      8 |  December | 2013 |
|  1 |      8 |   January | 2014 |

答案 1 :(得分:0)

希望这会对你有所帮助。

DECLARE @TEMP TABLE(ID INT,TENANT INT , DTSTART DATETIME,DTEND DATETIME)
INSERT INTO @TEMP VALUES(1,8,'2013-01-08 00:00:00.000','2014-01-01 00:00:00.000')

--You can create a function with the given logic
--It receives STARTDATE and ENDDATE

DECLARE @STARTDATE DATETIME =  (SELECT DTSTART FROM @TEMP),
        @ENDDATE DATETIME = (SELECT DTEND FROM @TEMP)

DECLARE @S INT = CAST(@STARTDATE AS INT)
DECLARE @E INT = CAST(@ENDDATE AS INT)
DECLARE @TAB TABLE (ID INT, DT DATETIME)

WHILE @S <= @E
BEGIN
    INSERT INTO @TAB VALUES (@S,CAST(@S AS DATETIME))
    SET @S = @S + 1
END

SELECT      TEMP.ID,TEMP.TENANT,[Mname] MONTH,[Y] YEAR FROM (
SELECT      DATEPART(YEAR,DT) [Y],DATEPART(MONTH,DT) [Mnum],DATENAME(MONTH,DT) [Mname] FROM @TAB
GROUP BY    DATEPART(YEAR,DT),DATEPART(MONTH,DT),DATENAME(MONTH,DT)) LU,@TEMP TEMP
ORDER BY    [Y],[Mnum]

结果:

enter image description here

相关问题