2015-10-16 55 views
1

我有大约30,000条记录,我需要分割Description字段,到目前为止,我似乎只能在Excel中实现这一点。一个例子Description是:如何在SQL Server中完成此Excel功能?

1USBCP 2RJ45C6 1DVI 1DP 3MD 3MLP HANDS 

下面是我的Excel函数:

=TRIM(MID(SUBSTITUTE($G309," ",REPT(" ",LEN($G309))),((COLUMNS($G309:G309)-1)*LEN($G309))+1,LEN($G309))) 

这则分布在10分Excel列拖,并在每个空间拆分description领域。

我看到很多关于在SQL中分割字符串的问题,但它们似乎只覆盖一个空格,而不是多空格。

回答

1

SQL服务器中没有简单的功能来拆分字符串。至少我不知道。我通常使用一些在前段时间在互联网上找到的技巧。我将其修改为您的示例。

诀窍是,首先我们试图找出我们需要多少列。我们可以通过检查字符串中有多少空串来完成。最简单的方法是使用字符串 - 长度不超过空字符串。 之后,对于每个字符串,我们尝试按位置查找每个单词的开始和结束。最后,我们通过开始和结束位置简单地剪切字符串,并将其分配给coulmns。详细信息在查询中。玩的开心!

CREATE TABLE test(id int, data varchar(100)) 

INSERT INTO test VALUES (1,'1USBCP 2RJ45C6 1DVI 1DP 3MD 3MLP HANDS') 
INSERT INTO test VALUES (2,'Shorter one') 

DECLARE @pivot varchar(8000) 
DECLARE @select varchar(8000) 

SELECT 
     @pivot=coalesce(@pivot+',','')+'[col'+cast(number+1 as varchar(10))+']' 
FROM 
     master..spt_values where type='p' and 
     number<=(SELECT max(len(data)-len(replace(data,',',''))) FROM test) 

SELECT 
    @select=' 
     select p.* 
     from (
     select 
      id,substring(data, start+2, endPos-Start-2) as token, 
      ''col''+cast(row_number() over(partition by id order by start) as varchar(10)) as n 
     from (
      select 
       id, data, n as start, charindex('','',data,n+2) endPos 
       from (select number as n from master..spt_values where type=''p'') num 
       cross join 
       (
        select 
         id, '' '' + data +'' '' as data 
        from 
         test 
       ) m 
      where n < len(data)-1 
      and substring(odata,n+1,1) = '','') as data 
     ) pvt 
     Pivot (max(token)for n in ('[email protected]+'))p' 


EXEC(@select) 

在这里你可以找到例子SQL Fiddle

我没注意到你想摆脱多个空格的。 要做到这一点,请创建一些功能preprare您的数据:

CREATE FUNCTION dbo.[fnRemoveExtraSpaces] (@Number AS varchar(1000)) 
Returns Varchar(1000) 
As 
Begin 
Declare @n int -- Length of counter 
Declare @old char(1) 

Set @n = 1 
--Begin Loop of field value 
While @n <=Len (@Number) 
    BEGIN 
    If Substring(@Number, @n, 1) = ' ' AND @old = ' ' 
     BEGIN 
     Select @Number = Stuff(@Number , @n , 1 , '') 
     END 
    Else 
     BEGIN 
     SET @old = Substring(@Number, @n, 1) 
     Set @n = @n + 1 
     END 
    END 
Return @number 
END 

之后使用新版本,消除多余的空格。

DECLARE @pivot varchar(8000) 
DECLARE @select varchar(8000) 

SELECT 
     @pivot=coalesce(@pivot+',','')+'[col'+cast(number+1 as varchar(10))+']' 
FROM 
     master..spt_values where type='p' and 
     number<=(SELECT max(len(dbo.fnRemoveExtraSpaces(data))-len(replace(dbo.fnRemoveExtraSpaces(data),' ',''))) FROM test) 

SELECT 
    @select=' 
     select p.* 
     from (
     select 
      id,substring(data, start+2, endPos-Start-2) as token, 
      ''col''+cast(row_number() over(partition by id order by start) as varchar(10)) as n 
     from (
      select 
       id, data, n as start, charindex('' '',data,n+2) endPos 
       from (select number as n from master..spt_values where type=''p'') num 
       cross join 
       (
        select 
         id, '' '' + dbo.fnRemoveExtraSpaces(data) +'' '' as data 
        from 
         test 
       ) m 
      where n < len(data)-1 
      and substring(data,n+1,1) = '' '') as data 
     ) pvt 
     Pivot (max(token)for n in ('[email protected]+'))p' 


EXEC(@select) 
0

我可能不理解你的问题,但所有你是这个公式在这样做,可以做到几乎完全在SQL一样。我看到有人已经回答,但在我看来,当你能做到这一点时,怎样才能做到这一点呢?我可能错了。但是在这里。

declare @test as varchar(100) 
set @test='abcd1234567' 

select right(@test,2) 
, left(@test,2) 
, len(@test) 
, case when len(@test)%2>0 
then left(right(@test,round(len(@test)/2,0)+1),1) 
else left(right(@test,round(len(@test)/2,0)+1),2) end 

结果

67 ab 11 2 

所以右,左,长度和中期都可以实现。

如果空格是“substring”分隔符,那么:我不太清楚do的实际语法 - 虽然在sql选择中,我也没有真正做到这一点,但我不明白为什么它应该不可能。如果它不起作用,那么你需要一个临时表,如果这不起作用,你需要一个游标。这个游标将是一个外部循环,每次只能读取和处理一个字符串。或者你可以做更聪明的事情。我只是一个新手。

declare @x varchar(1) 
declare @n integer 
declare @i integer 
declare @str varchar(100) -- this is your description. Fetch it and assign it. if in a cursor just use column-name 
set @x = null 
set @n = 0 
set @i = 0 
while n < len(@str) 
while NOT @x = " " 
begin 
set @x = left(right(@str,n),1) 
n = n+1 
end 
--insert into or update @temptable blablabla here. 

使用i和n来定位子字符串,然后离开(右())它。或者你可以选择它,但如果子字符串的数量很长,那是一个混乱的过程。继续:

set i = n 
set @str = right(@str, i) -- this includes the " ". left() it out at will. 
end 

现在,最后的评论中,或许应该是,如果你在最后一个“子”第三循环检查,因为我现在看到当它到达结束这段代码将抛出错误。或者将@str末尾的空白空间“添加”,这也将起作用。但我的时间到了。至少这是一个建议。