sql 聚合和拆分

sql aggregate and split

我有这个 table Table_1 :

pk Column_1
1  addcd
2  swrrh
3  dggdd
4  wdffa

我想将结果合并并拆分为 4 个字母,这样 return 就像这样

addc
dswr
rhdg
gddw
dffa

注意:剩下的字母将被丢弃

我尝试使用 string_agg,但我不知道下一步该做什么。

这使用 STRING_AGG 将字符串聚合成一个长字符串,然后使用 Tally Table 拆分为新行。 假定 您有一个列可以排序。如果你不这样做,你就无法实现你想要的,因为 table 中的数据存储在 无序 堆中。

CREATE TABLE dbo.YourTable (YourID int IDENTITY,
                            Yourcolumn varchar(5));

INSERT INTO dbo.YourTable (Yourcolumn)
VALUES('addcd'),
      ('swrrh'),
      ('dggdd'),
      ('wdffa');
GO

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS( 
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1 AS I
    FROM N N1, N N2, N N3, N N4), --This is likely over kill here, but I've assumed you'll have a much larger data set
Agg AS(
    SELECT STRING_AGG(YT.YourColumn,'') WITHIN GROUP (ORDER BY YT.YourID)   AS YourString
    FROM dbo.YourTable YT)
SELECT SUBSTRING(A.YourString,(I*4)+1,4)
FROM Tally T
     CROSS JOIN Agg A
WHERE SUBSTRING(A.YourString,(I*4)+1,4) <> '';
GO

DROP TABLE dbo.YourTable;

db<>fiddle

此解决方案适用于旧版本的 SQL 服务器。 Larnu 的回答在更新的版本中是正确的。

让我们使用递归 CTE。这个想法是创建一个大字符串,然后将其切成小块。太好玩了!

with tt as (
      select t.*, row_number() over (order by pk) as seqnum
      from t
     ),
     bigstring as (
      select convert(varchar(max), column_1) as bigstring, seqnum
      from tt
      union all
      select concat(bigstring.bigstring, tt.column_1), tt.seqnum
      from bigstring join
           tt
           on tt.seqnum = bigstring.seqnum + 1
     ),
     string4 as (
      select top (1) left(bigstring, 4) as string4, stuff(bigstring, 1, 4, '') as rest4, 1 as lev
      from bigstring
      order by len(bigstring.bigstring) desc
      union all
      select left(rest4, 4), stuff(rest4, 1, 4, ''), lev + 1
      from string4
      where rest4 > ''
     )
select string4.string4
from string4
order by lev;

一个查询中有两个递归 CTE!

Here 是一个 db<>fiddle.