【问题标题】:sql aggregate and split [closed]sql聚合和拆分[关闭]
【发布时间】:2019-12-25 09:25:10
【问题描述】:

我有这张表 Table_1:

pk Column_1
1  addcd
2  swrrh
3  dggdd
4  wdffa

我想将结果合并并拆分为 4 个字母,这些字母将返回类似这样的内容

addc
dswr
rhdg
gddw
dffa

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

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

【问题讨论】:

  • 假设那么您使用的是 SQL Server 2017?
  • @Larnu,是的,我使用的是 SQL Server 2017
  • 你有订购栏吗?
  • @EzLo,对不起,我忘了添加主键,用作排序列
  • @Gordon Linoff,不使用 strigg_agg 是否可行?

标签: split string-agg


【解决方案1】:

这使用STRING_AGG 将字符串聚合成一个长字符串,然后使用一个 Tally 表拆分成新的行。 假设您有一个列可供订购。如果你不这样做,你就无法实现你所追求的,因为表中的数据存储在一个无序堆中。

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

【讨论】:

  • 谢谢@Larnu,我试过这个并且它的工作,但我改变了 WHERE SUBSTRING(A.YourString,(I*4)+1,4) '' 到 WHERE len(SUBSTRING(A .YourString,(I*4)+1,4)) = 4;排除剩余的字符。但是现在我怀疑我是否会使用 string_agg,因为 Gordon Linoff 上面提到 string_agg 不能保证正确的排序。
  • @metal 他的陈述是错误的,如果您有要订购的列,您可以...这就是为什么我的STRING_AGG 表达式 一个ORDER BY 子句。
【解决方案2】:

此解决方案适用于旧版本的 SQL Server。 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 是一个 dbfiddle。

【讨论】:

  • 谢谢!这是可行的,但我添加 where len(string4) = 4 以排除剩余部分。
  • rCTE 的问题在于,顾名思义,它是递归的。对于大型数据集,这可能会很慢。
  • @Larnu,我同意你的观点,我试图显示详细的执行计划,结果是“语句终止。在语句完成之前,最大递归 100 已用尽”。现在我将保留这个问题。
  • STRING_AGG 解决方案在这里可以很好地工作@metal。它不会递归,就像我说的那样,戈登关于订购的说法是错误的;因为这些是使用该函数时关于排序的明确记录部分。如果不确定,请先进行测试。
  • @Larnu 。 . .我删除了 cmets 并赞成您的回答。我离开这个只是因为它适用于 SQL Server 的最新但 pre-string_agg() 版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多