将所有以前的列合并到当前列

Combine all previous columns to the current column

我有一个 table 术语,我正在使用 SQL Server 2014

termID   termname
  1       term1
  2       term2
  3       term3
  4       term4

我想要这样的结果

 termID   termname
  1         term1
  2         term1 and term2
  3         term1 and term2 and term3
  4         term1 and term2 and term3 and term4

我已使用 LAG() 完成此操作,但我只能获得前一个值。我需要获取所有以前的列值。

 select termid, CASE WHEN ISNULL(prev_word,'')<>'' THEN prev_word+' and '+ termname ELSE termname END
from (
    select termID, 
           lag(termname) over (order by termID) as prev_word,
           termname
    from terms
) as t

一些数据库(例如 Postgres)支持 string_agg() 作为 window 函数,这让你可以这样写:

select
    temid,
    string_agg(termname, ' and ') over(order by termid) termname
from terms

...不幸的是,SQL 服务器不支持此语法(还?)。

另一种方法是递归查询。我不会假设 termid 总是从 1 开始并且总是没有间隙地递增,所以这首先用 row_number() 重新编号行,然后迭代遍历数据集,逐步累积字符串:

with 
    data as (
        select t.*, row_number() over(order by termid) rn from terms t
    ),
    cte as (
        select termid, cast(termname as varchar(max)) termname, rn
        from data 
        where rn = 1
        union all
        select d.termid, c.termname + ' and ' + d.termname, d.rn
        from cte c
        inner join data d on d.rn = c.rn + 1
    )
select termid, termname from cte order by termid        

如果列表中的值超过 100 个,则需要在查询的最后添加 option (maxrecursion 0)(否则会达到 100 次迭代的默认限制)。

Demo on DB Fiddle:

termid | termname                           
-----: | :----------------------------------
     1 | term1                              
     2 | term1 and term2                    
     3 | term1 and term2 and term3          
     4 | term1 and term2 and term3 and term4