开始日期和结束日期之间的一串季度日期

时间:2017-07-17 14:34:07

标签: sql sql-server-2008-r2 common-table-expression

我有一个递归的cte工作来生成@startDate和@endDate之间的日期列表,按季度递增。

declare @startDate datetime
declare @endDate datetime

set @startDate= '01-jan-2014'
set @endDate= '01-jul-2017'

;With cte
As
( Select @startDate date1
Union All
Select DateAdd(Month,3,date1)   From cte where date1 < @endDate 
) select cast(cast( Year(date1)*10000 + MONTH(date1)*100 + 1 as 
varchar(255)) as date) quarterlyDates From cte

这会产生:

quarterlyDates
--------------
2014-01-01
2014-04-01
2014-07-01
2014-10-01 ...

我想将cte的输出连接成一个字符串,如下所示:

"'01-jan-2014', '01-apr-2014, '01-jul-2014'..." 

等。我对这最后一步感到困惑 - 任何帮助都将不胜感激!

3 个答案:

答案 0 :(得分:1)

不确定你为什么要...但只是将底部cte包装好并使用东西。

declare @table table(quarterlyDates date)
insert into @table
values
('2014-01-01'),
('2014-04-01'),
('2014-07-01'),
('2014-10-01')

SELECT stuff((
    SELECT ', ' + cast(quarterlyDates as varchar(max))
    FROM @table
    FOR XML PATH('')
    ), 1, 2, '')

在您的代码中......虽然第二次CTE不是必需的,但为了清楚起见我留下了它。

declare @startDate datetime
declare @endDate datetime

set @startDate= '01-jan-2014'
set @endDate= '01-jul-2017'

;With cte
As
( Select @startDate date1
Union All
Select DateAdd(Month,3,date1)   From cte where date1 < @endDate 
), 

cte2 as(
select cast(cast( Year(date1)*10000 + MONTH(date1)*100 + 1 as 
varchar(255)) as date) quarterlyDates From cte)

SELECT stuff((
    SELECT ', ' + cast(quarterlyDates as varchar(max))
    FROM cte2
    FOR XML PATH('')
    ), 1, 2, '');

答案 1 :(得分:1)

FOR XML Pathtype指令一起使用,以避免在结果

中编码非法字符
;WITH cte 
     AS (SELECT @startDate date1 
         UNION ALL 
         SELECT Dateadd(month, 3, date1) 
         FROM   cte 
         WHERE  date1 < @endDate) 
SELECT Stuff((SELECT ',' + CONVERT(VARCHAR(15), date1, 106) quarterlyDates 
              FROM   cte 
              FOR xml path, type).value('.[1]', 'nvarchar(max)'), 1, 1, ''); 

注意:我更改了最终select中不需要的操作。在106函数中使用样式Convert来获取所需的输出格式

答案 2 :(得分:1)

迟到的答案,只是为了好玩。

示例

declare @startDate datetime = '01-jan-2014'
declare @endDate datetime   = '01-jul-2017'

;With cte
As
( Select date1 = @startDate
        ,dates = ''''+convert(varchar(max),convert(varchar(11),@startDate,113))+''''
  Union All
  Select DateAdd(Month,3,date1)   
        ,cte.dates+','''+convert(varchar(11),DateAdd(Month,3,date1)   ,106)+''''
   From cte where date1 < @endDate 
) 
Select Top 1 with ties 
       Dates=lower(replace(Dates,' ','-') )
 From cte
 Order By Date1 Desc

<强>返回

'01-jan-2014','01-apr-2014','01-jul-2014','01-oct-2014','01-jan-2015','01-apr-2015','01-jul-2015','01-oct-2015','01-jan-2016','01-apr-2016','01-jul-2016','01-oct-2016','01-jan-2017','01-apr-2017','01-jul-2017'