将行连接成列(NO FOR XML PATH('') 和递归 CTE)- SQL Server 2012

Concatenate rows into columns (NO FOR XML PATH('') and recursive CTEs) - SQL Server 2012

我手头有一个非常特殊的问题。

简介:我在数据库中有两列需要 "group concatenate",在 MySQL 我会简单地使用 GROUP_CONCAT 来获得所需的结果,在 [=40] =] Server 2017 和我会使用 STRING_AGG,我遇到的问题是 SQL Server 2012,它没有这个功能。

现在,在正常情况下我会使用 FOR XML PATH('') 来获得解决方案,这是不可行的,因为我 运行 来自第三个源应用程序中的编辑器的查询,错误是我得到的是

FOR XML PATH('') can't be used inside a cursor

为了论证,我们假设使用这个函数是完全不可能的。

我试过使用递归CTE,但是,由于执行时间,它不可行,UNION ALL占用太多资源,无法正常执行(我正在使用数据进行报告)。

由于数据的敏感性,我不会post数据的屏幕截图,假设只有两列,一列有一个 id(多个相同的 id),一列有需要的数据要连接(一些字符串)。目标是将第一列中所有相同 ID 的第二列连接起来,显然在这个过程中使它与众不同。

示例: 输入:

col1  col2 
1     a
1     b
2     a
3     c

输出:

col1  col2 
1     a/b
2     a
3     c

有没有人对如何做到这一点有创意?

您的示例输出似乎有误,因为 'a/b' 应该是值 2。

尝试以下操作:

declare @t table (col1  int, col2 varchar(100))
insert into @t select 1, 'a'
insert into @t select 2, 'b'
insert into @t select 2, 'a'
insert into @t select 3, 'c'

declare @final_table table (col1  int, col2 varchar(100), col2_all varchar(1000))
insert into @final_table (col1, col2)
select * from @t

declare @col2_all varchar(1000)
declare @Name sysname

update  @final_table 
SET @col2_all = col2_all = COALESCE(CASE COALESCE(@Name, '') 
                                        WHEN col1 THEN @col2_all + '/' + col2
                                        ELSE col2 END, ''), 
                                    @Name = col1;

select col1, col2_grouped = MAX(col2_all)
from @final_table
group by col1

使用 CTE:

;with cte(col1,col2_grouped,rn)
as
(
  select col1, col2 , rn=ROW_NUMBER() over (PARTITION by col1 order by col1)
  from @t
)
,cte2(col1,final_grouped,rn)
as
(
select col1, convert(varchar(max),col2_grouped), 1 from cte where rn=1
union all
select cte2.col1, convert(varchar(max),cte2.final_grouped+'/'+cte.col2_grouped), cte2.rn+1
from cte2
inner join cte on cte.col1 = cte2.col1 and cte.rn=cte2.rn+1
)
select col1, MAX(final_grouped) col2_grouped from cte2 group by col1

请参阅db<>fiddle here

如果您知道需要连接在一起的最大值数,则可以使用条件聚合:

select col1,
       stuff( concat(max(case when seqnum = 1 then '/' + col2 end),
                     max(case when seqnum = 2 then '/' + col2 end),
                     max(case when seqnum = 3 then '/' + col2 end),
                     max(case when seqnum = 4 then '/' + col2 end),
                     max(case when seqnum = 5 then '/' + col2 end)
                    ), 1, 1, ''
            ) as col2s                     
from (select t.*, 
             row_number() over (partition by col1 order by col2) as seqnum
      from t
     ) t
group by col1;

您可以使用以下方式获得最大数量:

select top (1) count(*)
from t
group by col1;