【问题标题】:Convert single row with comma seperator into multiple Column [duplicate]将带有逗号分隔符的单行转换为多列[重复]
【发布时间】:2020-09-29 22:35:18
【问题描述】:

如果我发出

SELECT ID FROM TestAhmet 

我得到这个结果:

1,2,3,4,5

但我真正需要的是所有值用逗号分隔的多列,如下所示:

1
3
5
2
4

我该怎么做?

【问题讨论】:

  • 如果可能的话,我建议首先将表格更改为不存储逗号分隔值。而是将这些值放在与 TestAhmet 表具有多对一关系的单独表中。
  • 你想在服务器端还是客户端实现?
  • 你好大师,服务器端。
  • @Subash 首先不存储此类值。这是一个错误。在主流支持的所有 SQL Server 版本(2016+)中,您可以使用STRING_SPLIT。您还会发现很多类似的 SO 问题。 XML Path 技术可能是最快的
  • 任何版本的最佳选择是拆分服务器上的数据并将其存储在单独的表中,存储在多行上,就像任何其他数据一样。另一种选择是将数据存储为 XML 并使用 XML 方法进行查询。

标签: sql-server string csv join sql-server-2012


【解决方案1】:

如果您运行的是 SQL Server 2016 或更高版本,则可以使用table-valued function string_split()

select value
from TestAhmet t
cross apply string_split(t.id, ',')

【讨论】:

  • 您好 GMB,感谢您的更新,运气不好我正在使用 sql 2012。请提供该版本的解决方案。
  • @Subash SO 不是免费的代码编写服务。拆分字符串一直是(并且可能会继续是)一个不变的话题;稍加搜索就会发现许多代码示例,它们可以为任何版本的 sql server 完成此操作。
  • @Subash 我已经编辑了您的问题以添加 sql 2012 标签,因此得到更准确的答案
  • @Subash 在 2012 年可以使用替换来形成 XML 节点和 XML 相关函数
【解决方案2】:

您可以将此查询作为一个函数并跨过程使用。

DECLARE @list varchar(MAX)= '1,2,3,4,5',
        @pos        int,
        @nextpos    int,
        @valuelen   int
DECLARE  @tbl TABLE (number int  NULL)

   SELECT @pos = 0, @nextpos = 1

   WHILE @nextpos > 0
   BEGIN
      SELECT @nextpos = charindex(',', @list, @pos + 1)
      SELECT @valuelen = CASE WHEN @nextpos > 0
                              THEN @nextpos
                              ELSE len(@list) + 1
                         END - @pos - 1
      INSERT @tbl (number)
         VALUES (convert(int, substring(@list, @pos + 1, @valuelen)))
      SELECT @pos = @nextpos
   END

   SELECT * FROM @tbl

【讨论】:

    【解决方案3】:

    您可以使用 SQL Server 2012 上提供的与 XML 相关的函数

    参考:XML nodes() functionXML value() function

    DECLARE @text_to_split nvarchar(100) = '1,10,4,6'
    
    SELECT document.node.value('.', 'int') as id
    FROM
         (SELECT CAST('<content><x>' + REPLACE(@text_to_split, ',', '</x><x>') + '</x></content>' AS XML) as content) xml_data
         CROSS APPLY xml_data.content.nodes('/content/x') as document(node)
    

    输出是:

    1
    10
    4
    6
    

    说明

    我们所做的是将该数据转换为有效的 XML:
    CAST('<content><x>' + REPLACE(@text_to_split, ',', '</x><x>') + '</x></content>' AS XML) as content
    

    然后我们创建一个CROSS APPLY 以便能够将其作为一个结构化的 XML 数据表处理

    CROSS APPLY xml_data.content.nodes('/content/x') as document(node)
    

    最后我们提取 XML 节点的内容并将其转换为整数

    SELECT document.node.value('.', 'int') as id
    

    【讨论】:

      猜你喜欢
      • 2010-10-27
      • 2016-01-29
      • 1970-01-01
      • 2012-02-01
      • 2014-08-24
      • 1970-01-01
      • 2015-06-10
      • 2020-04-07
      相关资源
      最近更新 更多