【问题标题】:Split 1 column data to multiple column with separator as double space in SQL Server [closed]在SQL Server中将1列数据拆分为多列,分隔符为双空格[关闭]
【发布时间】:2018-08-17 06:34:08
【问题描述】:

以下是我的记录

13;16;AB BC  13;16;BC CD  13;16;CD DE

我想要下面的结果

|  Column 1 | Column 2  |  column 3 | 
|-----------|-----------|-----------|
|  13       |        16 |    AB BC  | 
|  13       |        16 |    BC CD  |  
|  13       |        16 |    CD DE  |  

注意:这里我想用双空格分割记录,然后用(;)进行内部分割。

虽然我在这里有三列,但在实践中可能更多。因此,解决方案需要灵活。

【问题讨论】:

  • SQL Server 老实说并不是进行这种数据清理的最佳场所。在将数据导入 SQL Server 之前,您是否有机会使用 R 之类的东西来处理这个问题?
  • 不,我只有 SQL 数据。
  • 然后您可以将这些数据导出到一个平面文件并从那里开始。这是非规范化数据,并不真正属于数据库 IMO。如果您真的想在 SQL Server 中处理这个问题,我认为您需要编写自定义 UDF 或 proc。
  • @ChetanSanghani 如果您已经尝试了 6 个小时,为什么没有在您的问题中包含您的尝试,或者您为什么没有现在编辑您的问题?如果您将其包含在内,我可能会节省很多时间来编写我的答案,如果您这样做,其他志愿者会更乐意为您提供其他答案。
  • 根据我自己的回答中的 cmets,这个问题似乎比我们任何人想的都不清楚;详细信息仅在 cmets 中给出答案,而不是在问题中显示(OP 尚未在此处解决 cmets)。因此,我投票决定以不清楚的方式结束这个问题。对于 OP,请参阅制作的 cmets,并请相应地更新您的问题。

标签: sql-server split


【解决方案1】:

用好Replace函数,配合动态代码

DECLARE @X VARCHAR(100)='13;16;AB BC  13;16;BC CD  13;16;CD DE'

DECLARE @SQL VARCHAR(MAX)=''

SELECT @SQL = REPLACE( '
SELECT * FROM (
SELECT '''+REPLACE(@X,'  ',''' UNION ALL 
SELECT '''),';',''',''') + '''
)AS TAB(COL1,COL2,COL3)
'

EXEC(@SQL)

结果

COL1    COL2    COL3
13      16      AB BC
13      16      BC CD
13      16      CD DE

【讨论】:

  • 谢谢Shakeer,但是这里的数据不会固定到3列,可以超过3列
  • 你没有在问题中提到它@ChetanSanghani
  • 是的,但是现在我要更新给你。
  • 它也适用于超过 3 列。但是所有集合都应该有相同的列数。 @ChetanSanghani
  • 您能否将其包含在您的示例数据和所需的输出中? @ChetanSanghani
【解决方案2】:

这不是一个理想的解决方案,并根据 OP 对另一个答案的评论做出一些猜测“这里的数据不会固定为 3 列,它可以超过 3 列” .

因此,我制作了自己的样本数据并进行了猜测。请注意,这使用了delimitedsplit8k,因此您需要它才能使用此解决方案:

USE Sandbox;
GO

CREATE TABLE dbo.StringsTable (ID int IDENTITY(1,1), --No idea if you have this, but sort order might be important
                               SomeString varchar(8000));

--insert sample data
INSERT INTO dbo.StringsTable (SomeString)
VALUES ('13;16;AB BC'),
       ('13;16;BC CD'),
       ('13;16;CD DE');
--Some more data, the OP says that can have strings with more (and maybe less) than 3 delimiters, but "forgot" to supply such examples...
INSERT INTO dbo.StringsTable (SomeString)
VALUES ('10'),
       ('19;124;BC CD;29;ZY XY'),
       ('29;AB CF'),
       ('43;BE HG;GY TY;18');
GO

SELECT *
FROM dbo.StringsTable;
GO

DECLARE @SQL nvarchar(MAX);
--Get the maximum number of parts
WITH MaxParts AS(
SELECT MAX(DS.ItemNumber) AS MaxPart
FROM dbo.StringsTable ST
     CROSS APPLY dbo.DelimitedSplit8K(ST.SomeString,';') DS),
--Need a tally table now
N AS(
    SELECT *
    FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) V(N)),
Tally AS (
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS i
    FROM N N1 --10
         CROSS JOIN N N2 --100
         CROSS JOIN N N3 --1000
    ) --If you have more than 1000 parts then repeat, but remember, delimitedSplit8K expectes a varchar(8000), not MAX
      --Of course, also fee free to lower the number the tally returns, if it's not needed
SELECT @SQL =
       N'SELECT ' +
       STUFF((SELECT N',' + NCHAR(10) + '       MAX(CASE DS.ItemNumber WHEN ' + QUOTENAME(T.i,N'''') + N' THEN DS.Item END) AS ' + QUOTENAME('Column' + CONVERT(nvarchar(4),T.i))
              FROM Tally T
              WHERE T.i <= (SELECT MaxPart FROM MaxParts MP)
              ORDER BY t.i
              FOR XML PATH(N'')),1,9,'') + NCHAR(10) +
       N'FROM dbo.StringsTable ST' + NCHAR(10) +
       N'     CROSS APPLY dbo.DelimitedSplit8K(ST.SomeString,'';'') DS' + NCHAR(10) +
       N'GROUP BY ST.ID' + NCHAR(10) + 
       N'ORDER BY ST.ID;'
PRINT @SQL; --your best friend
--Run the SQL
EXEC sp_executesql @SQL;

GO
DROP TABLE dbo.StringsTable;
GO

【讨论】:

  • (我已尝试更新问题以注意新的约束。)
  • @Larnu:我已经检查了你的解决方案,它有一个小错误
  • @ChetanSanghani 你愿意分享那个“错误”吗?该 SQL 本身似乎提供了您的 ague 要求所需的内容。不要忘记,正如许多 cmets 提醒您的那样,我基本上是在对您的要求视而不见的情况下编写了该答案,因为它们丢失了。这真的是一个错误,还是球门柱(再次)移动?
  • @Larnu:我已经检查了您的解决方案,但它有一个小错误。它给我的结果类似于 Column1: 13 , Column2 : 16, Column3: AB BC 13。在第 3 列中应该只有 AB BC。 13 应该在下一列中
  • @ChetanSanghani 你看到的是哪一行?我的示例数据中没有具有值 '13;16;AB BC;13' 的行,因此该值不是来自我的示例数据和解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-04-27
  • 2018-03-17
相关资源
最近更新 更多