Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 将VARCHAR列拆分为多个列_Sql Server_Sql Server 2014 - Fatal编程技术网

Sql server 将VARCHAR列拆分为多个列

Sql server 将VARCHAR列拆分为多个列,sql-server,sql-server-2014,Sql Server,Sql Server 2014,我正在努力将列中的数据拆分为多个列。 我有客户姓名的数据,数据需要清理,因为可能存在重复数据,我还需要为未来的数据建立新的标准。 我已经能够成功拆分字符串中的前两个单词,但无法拆分进一步的数据 我只有读取权限。所以我不能创建任何函数 例如: 客户名称:伊利诺伊理工学院 我的查询只会在一列中显示“Illinois”,在另一列中显示“Institute of Technology”。考虑到分隔符是“空格”,我希望将每个单词分隔成单独的列。我不知道如何识别第二个空间和其他空间 我也尝试过使用“pars

我正在努力将列中的数据拆分为多个列。 我有客户姓名的数据,数据需要清理,因为可能存在重复数据,我还需要为未来的数据建立新的标准。 我已经能够成功拆分字符串中的前两个单词,但无法拆分进一步的数据

我只有读取权限。所以我不能创建任何函数

例如:

客户名称:伊利诺伊理工学院

我的查询只会在一列中显示“Illinois”,在另一列中显示“Institute of Technology”。考虑到分隔符是“空格”,我希望将每个单词分隔成单独的列。我不知道如何识别第二个空间和其他空间

我也尝试过使用“parsename”函数,但我觉得这会给清理数据带来更多困难

select name, 
left (name, CHARINDEX(' ', name)) as f,
substring(name, CHARINDEX(' ', name)+1, len(name)) as s
from customer

您没有提到一旦检索到数据,您打算对其执行什么操作。由于您只有读取权限,因此无法将其存储在表中。您可能没有想到的是创建一个本地数据库,在那里您确实有写权限并在那里工作。最简单的方法是获取数据库的副本,但也可以使用完全限定名访问只读数据库

至于您的字符串拆分需求,我可以为您指出一种很棒的拆分字符串的方法,该方法由一位名叫Jeff Moden的先生创建。您可以在此处找到一篇讨论此问题的文章以及代码链接:

虽然这是一篇非常有信息量的文章,因为其中大部分内容都是关于性能测试之类的,您可能想跳过其中的大部分内容,直接阅读代码,但请尝试挑选讨论功能性的内容并阅读,因为代码最多只会让不熟悉的人觉得非常规

代码创建了一个函数,但是因为您没有权限这样做,所以您必须从函数中删除肉并直接使用它

我将尝试提供一些方法概述,以帮助您开始

这种方法的核心是一个计分表。如果您不熟悉该术语(也称为数字表),它基本上是一个表,其中每一行包含一个整数,而这些行基本上是某个范围内的所有整数的集合,通常相当大。那么,理货台如何帮助拆分字符串呢?通过将理货表连接到包含要拆分的字符串的表,并通过查看由理货表编号索引的1个字符的子字符串,使用where子句来标识分隔符,可以实现神奇的效果。SQL Server自然的基于集合的操作然后一次搜索所有分隔符,然后选择列表提取分隔符括起来的子字符串。它真的很聪明,速度也很快

当您进入代码时,函数的第一部分可能看起来很奇怪(因为它是),但这是必要的,因为您只有读取权限。它基本上是使用SQL Server的公共表表达式(Common Table Expression,CTE)功能来动态构建内部理货表,使用一些您并不真正需要理解的丑陋逻辑(但如果您想深入研究,即使丑陋也很聪明)。由于该表只是查询的本地表,因此不会违反您的只读权限

它还使用CTE来表示起始索引和分隔子字符串的长度,因此最终的查询非常简单,生成的行后面有一个行号,后面是从原始数据中拆分出来的字符串

我希望这能帮助您完成任务——它真的是工具箱中的一个不错的工具


编辑:我刚刚意识到您希望输出在单独的列中而不是行中。这相当困难,因为要拆分的每一列可能会生成不同数量的字符串,而且,您的列需要名称。如果您已经知道列名和输出字符串的数量,那么这将更容易,但仍然很棘手。可以调整拆分器中的行数据,以提供数据来源行的标识符,如果需要,行号可能有助于创建任意列名,但最大的问题是,仅使用读取权限时,您会发现按步骤处理事情相当棘手——CTE可以进一步用于此目的,但除非要求非常简单,否则您的代码可能会变得相当混乱。

编辑:这仅适用于SQL Server 2016及更高版本。OP拥有SQL Server 2014

这并不是一个很好的方法,但这里有一个方法可能适合您,根据一个示例进行了修改:

请注意以下几点:

  • 您必须在输出中显式声明列。您可以创建一些过于复杂的动态SQL,根据需要生成尽可能多的列名,但这会使修复问题和进行修改变得更加困难,而且您可能无法获得相同的查询优化
  • 由于(1)的原因,如果单词太多而无法满足您定义的列数,那么您最终将丢弃单词。请参见最后一个示例,id=4
  • 注意其他可能无法保持单词顺序的方法,或跳过重复单词的方法,例如示例id=3中的“of”

  • 我使用的是sql server 14.0。字符串分割功能在16.0Ah中可用,但您没有用sql server版本标记问题,我是如何知道的?:)我会留下这个答案,以防它对其他人提出类似的问题有所帮助。或者,看看这个问题及其答案:嗯,我对堆栈溢出还不熟悉。我可能忘了提这件事。但是你提供的链接非常有用。谢谢:)
    create table #customer (id int, name nvarchar(max))
    
    insert into #customer
    values  (1, 'Illinois Institute of Technology'), 
            (2, 'The City University of New York'), 
            (3, 'University of the District of Columbia'), 
            (4, 'Santa Fe University of Art and Design')
    
    ;   
    with c as(
    select id, name
          ,value
          ,row_number() over(partition by id order by (select null)) as rn
    from #customer
    cross apply string_split(name, ' ') as bk
    )
    select id, name
          ,[1]
          ,[2]
          ,[3]
          ,[4]
          ,[5]
          ,[6]
    from c
    pivot(
        max(value)
        for rn in([1],[2],[3],[4],[5],[6])  
    ) as pvt
    
    drop table #customer