2015-10-16 121 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末尾的空白空間「添加」,這也將起作用。但我的時間到了。至少這是一個建議。