我有大约30,000条记录需要拆分Description
字段,到目前为止,我似乎只能在Excel中实现这一点。示例Description
将是:
1USBCP 2RJ45C6 1DVI 1DP 3MD 3MLP HANDS
以下是我的Excel功能:
=TRIM(MID(SUBSTITUTE($G309," ",REPT(" ",LEN($G309))),((COLUMNS($G309:G309)-1)*LEN($G309))+1,LEN($G309)))
然后将其拖过十个Excel列,并在每个空格处拆分description
字段。
我已经看到很多关于在SQL中拆分字符串的问题,但它们似乎只覆盖了一个空格,而不是多个空格。
答案 0 :(得分:1)
SQL Server中没有简单的功能来分割字符串。至少我不知道。我通常会使用一些技巧,这些技巧是我前段时间在互联网上找到的。我把它修改为你的例子。
诀窍在于,首先我们要弄清楚我们需要多少列。我们可以通过检查字符串中有多少空字符串来实现。最简单的方法是长度为字符串 - 字符串长度没有空字符串。 在每个字符串之后,我们尝试按位置查找每个单词的开头和结尾。最后,我们通过开始和结束位置简单地剪切字符串并分配给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 ('+@pivot+'))p'
EXEC(@select)
您可以在此处找到SQL Fiddle
中的示例我没有注意到你想摆脱多个空格。 要做到这一点,请创建一些预先准备数据的功能:
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 ('+@pivot+'))p'
EXEC(@select)
答案 1 :(得分: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
所以右,左,长,中都可以实现。
如果空格是“子串”分隔符,那么:我不记得do-while内部选择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,这也可以。但我的时间到了。这至少是一个建议。