【问题标题】:SQL - Convert results into comma separated stringSQL - 将结果转换为逗号分隔的字符串
【发布时间】:2013-08-07 09:28:00
【问题描述】:

使用 StackOverflow 上的另一篇文章 (How to split date ranges based on months in SQL Server 2005) 我运行了一个 SELECT 语句,该语句按月拆分日期范围并在 SQL 中返回 2 列 (DateFrom, DateTo)。

DECLARE @SDate DATE = '2012/08/01'
DECLARE @EDate DATE = '2013/09/01'

SELECT 
    DATEADD(MONTH, n.Number, @SDate) as DateFrom, 
    DATEADD(day, -1, DATEADD(MONTH, n.Number, DATEADD(YEAR,-1,@EDate))) as DateTo
FROM 
    master.dbo.spt_values n
WHERE 
    n.Number < DATEDIFF(MONTH, @SDate, @EDate)
    AND n.Type = 'P'

我现在需要将返回的每一行添加到一个字符串中,将列分隔为| (Dateto|Datefrom),每一行分隔为,

例如,如果您运行上面的代码,结果将是(仅对于此示例,我只使用前 4 行,但我需要将它们全部放在一个字符串中):

R | Date From  |  Date To
1 | 2012-08-01 | 2012-08-31
2 | 2012-09-01 | 2012-09-30
3 | 2012-10-01 | 2012-10-30
4 | 2012-11-01 | 2012-11-30

代码:

DECLARE @stralldates VarChar(MAX)
/* SET @stralldates = INSERTCODE */
PRINT @stralldates

我需要 PRINT 才能返回:

2012-08-01|2012-08-31,2012-10-01|2012-10-30,2012-10-01|2012-10-30,2012-11-01|2012-11-30

我尝试了 StackOverflow 上其他类似问题(例如 CONCAT)的几个建议,但均未成功。

任何帮助或建议将不胜感激。

【问题讨论】:

    标签: sql-server


    【解决方案1】:
    set @StrAllDates = 
      stuff((select ','+convert(char(10), SDate, 121)+'|'+convert(char(10), dateadd(day, -1, dateadd(month, 1, SDate)), 121)
             from (
                  select dateadd(month, n.number, @SDate) as SDate
                  from master..spt_values as n
                  where n.number < datediff(month, @SDate, @EDate) and
                        n.type = 'P'
                  ) as T
             order by SDate
             for xml path('')), 1, 1, '')
    

    【讨论】:

    • 感谢您的帮助,这正是我所需要的!
    【解决方案2】:

    我只知道 Oracle 根据版本提供 wm_concat(未记录)或 listagg。

    【讨论】:

      【解决方案3】:

      您可以使用以下脚本以您想要的格式获取数据。它基本上使用合并方法进行连接。我创建了一个临时表来保存数据,然后用于迭代行。

      DECLARE @SDate DATE = '2012/08/01'
      DECLARE @EDate DATE = '2013/09/01'
      SELECT 
          DATEADD(MONTH, n.Number, @SDate) as DateFrom, 
          DATEADD(day, -1, DATEADD(MONTH, n.Number, DATEADD(YEAR,-1,@EDate))) as DateTo
      INTO #tmp_data
      FROM master.dbo.spt_values n
      WHERE 
      n.Number < DATEDIFF(MONTH, @SDate, @EDate)
      AND n.Type = 'P'
      
      declare @my_string varchar(8000);
      select @my_string = 
          coalesce( @my_string + ',', '') 
          + convert(varchar(10), d.DateFrom, 126) 
          + '|' + convert(varchar(10), d.DateTo, 126)  
      from #tmp_data d
      order by d.DateFrom
      select @my_string
      
      drop table #tmp_data
      

      另外,如果你想使用 row rumber,你可以通过在 select 子句中添加另一列来使用它 - ROW_NUMBER() OVER(ORDER BY n.Number) as RowNum

      【讨论】:

      • 此答案不保证日期按日期升序连接。只有 OP 会知道这是否有问题。
      • @Mikael Eriksson 我没有意识到你只能标记一个答案,我猜使用 temptables 无论如何都不会那么有效。但是感谢您的帮助 siddharth!
      • 谢谢本。 @MikaelEriksson - 从临时表中选择时,我们总是可以添加 order by 子句。
      • 这样的连接字符串是未记录的,即使使用 order by 子句,正确的行为也未定义。 Why SQL Server Ignores vaules in string concatenation when ORDER BY clause specified
      • 不知道!谢谢!
      【解决方案4】:

      以下查询将为您提供所需的逗号分隔字符串:

      DECLARE @Begin DATETIME
      DECLARE @End DATETIME
      Declare @test Table(startDate datetime, endDate datetime)
      DECLARE @listStr VARCHAR(MAX)
      SELECT @Begin = '20110101', @End = '20120101'
      
      Insert into @test
      SELECT DATEADD(MONTH, n.Number, @Begin) DateFrom, DATEADD(day, -1, DATEADD(MONTH, n.Number+1, @Begin)) DateTo
      FROM master.dbo.spt_values n
      WHERE 
          n.Number <= DATEDIFF(MONTH, @begin, @end)
      AND n.Type = 'P'
      
      select  @listStr =  COALESCE(@listStr+',' ,'')+ CONVERT(VARCHAR(10), startDate, 120) + '|' + CONVERT(varchar(10),endDate,120) from @test 
      select @listStr
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-20
        • 1970-01-01
        • 2019-11-18
        • 2018-08-16
        • 2013-09-30
        • 2017-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多