2014-06-26 79 views
3

我有一張表包含歷史表中的這樣的數據。特定字符串組之前的東西或插入字符串

MEMBER_ID COLORS 
1   1) Red 2) Blue 3) Green 

我需要修改或選擇數據,以便結果集看起來像這樣。

MEMBER_ID COLORS 
1   #1) Red #2) Blue #3) Green 

簡而言之,在數字和右括號之前插入英鎊。

我試過使用CHARINDEX,但我試過的東西沒有工作。

+0

將它永遠是個位數的? –

+0

是的,大部分在1到9之間。 – Asynchronous

+0

我在想你可以根據以下字符串來分割字符串:http://stackoverflow.com/questions/4266957/how-to-split-string-and-save-into-an -array-in -t -sql 然後追加你的# 然後將數據拉回到一起。 http://stackoverflow.com/questions/194852/concatenate-many-rows-into-a-single-text-string 我開始了一個小提琴。 http://sqlfiddle.com/#!6/4f6fa/24 –

回答

1

假設MS SQL Server ...最簡單的方法是: 選擇MEMBER_ID,REPLACE(REPLACE(REPLACE(COLORS,'1','#1'),'2','#2'),'3' ,'#3')AS顏色

+0

是的是SQL Server,問題是,你不知道顏色的數量。所以這些數字是不固定的。它可能是3或10.在這種情況下,替換不會像你所建議的那樣工作。 – Asynchronous

+0

你可以做到最大數量的顏色,你會有。如果你不會有超過10種顏色,只需10'REPLACE's。如果柱子的顏色少於10種,它不會造成任何傷害。它不是很優雅,如果你有數百種顏色,它會吸引人,但如果你只有1到9之間,這可能是最簡單的解決方案。 – Jerrad

+0

當你申請你的陳述時,兩位數字會發生什麼? '10)紅色11)藍色12)綠色' – mdisibio

2

我不確定您的數據有多可預測性,所以我會提供一個建議,並且您可以使用類似的PATINDEX s對其他任何角落案例進行擴展。

我在此建議假設每個文本可能與任何單個數字(例如「1)」),沒有前述空間開始,你只有一個或兩個數字指標(簡單地擴大我的建議更高的指數),而唯一轉換的數字是那些後面跟着一個parens的數字。

-- first update, done only once 
-- starts with 1) ...any single digit, no preceeding space, followed by parens 
;WITH TMP AS (SELECT Id FROM #SRC WHERE PATINDEX('[0-9][)]%', Colors) = 1) 
    UPDATE MyTable SET Colors = STUFF(Colors, 1, 0, '#') 
    WHERE Id IN (SELECT Id FROM TMP); 

-- (you could repeat the above for strings starting with a double digit, if necessary) 

-- next two updates are looped until pattern is no longer found 
DECLARE @affected int = 1; 
WHILE @affected > 0 
    BEGIN 
    -- e.g. 1) ...any single digit not yet converted and followed by parens 
    ;WITH TMP AS (SELECT Id FROM #SRC WHERE PATINDEX('%[^#0-9][0-9][)]%', Colors) > 1) 
     UPDATE MyTable SET Colors = STUFF(Colors, PATINDEX('%[^#0-9][0-9][)]%', Colors)+1, 0, '#') 
     WHERE Id IN (SELECT Id FROM TMP);  
    SET @affected = @@rowcount; 
    END 

SET @affected = 1;  
WHILE @affected > 0 
    BEGIN 
    -- e.g. 10) ...any two digits not yet converted and followed by parens 
    ;WITH TMP AS (SELECT Id FROM #SRC WHERE PATINDEX('%[^#0-9][0-9][0-9][)]%', Colors) > 1) 
     UPDATE MyTable SET Colors = STUFF(Colors, PATINDEX('%[^#0-9][0-9][0-9][)]%', Colors)+1, 0, '#') 
     WHERE Id IN (SELECT Id FROM TMP);  
    SET @affected = @@rowcount; 
    END 

所以,如果你開始使用這三行:

Id Colors 
1 1) Red 2) Blue 3) Green 
2 1) Red 20) Blue 30) Green 
3 1) Red 20) Blue 3) Green 
4 9) Red 10) Blue No.4 11) Green 

根據上述程序將產生:

Id Colors 
1 #1) Red #2) Blue #3) Green 
2 #1) Red #20) Blue #30) Green 
3 #1) Red #20) Blue #3) Green 
4 #9) Red #10) Blue No.4 #11) Green 
+0

我已經更新了我的答案,不要求索引先於空格。它只需要一個或兩個數字後跟一個parens。再次,這一切都取決於確切的要求。 – mdisibio

2

您可以使用Replace (Colors, ' 1', ' #1')命令到數字1轉換爲#1。並且必須對每個數字使用Replace命令。換句話說您的查詢必須寫爲以下幾點:

SELECT Member_Id, LTRIM(REPLACE(
         REPLACE(
          REPLACE(
           REPLACE(
            REPLACE(
             REPLACE(
              REPLACE(
               REPLACE(
                REPLACE(' '+Colors,' 1',' #1') 
                ,' 2',' #2') 
               ,' 3', ' #3') 
              ,' 4',' #4') 
             ,' 5',' #5') 
            ,' 6',' #6') 
           ,' 7',' #7') 
          ,' 8',' #8') 
         ,' 9',' #9')) AS Colors 
From YourTable 

另一種方法:

CREATE FUNCTION dbo.f(@T NVARCHAR(100)) 
RETURNS NVARCHAR(100) 
AS BEGIN 
    DECLARE @R NVARCHAR(100)='', 
      @IsDigit BIT = 0, 
      @Index INT = 1 
    WHILE @Index<=LEN(@T)BEGIN 
     IF (SUBSTRING(@T,@Index,1) IN ('1','2','3','4','5','6','7','8','9') AND @IsDigit = 0) BEGIN 
      SET @R = @R + '#'+SUBSTRING(@T,@Index,1) 
      SET @IsDigit = 1 
     END ELSE BEGIN 
      SET @R = @R + SUBSTRING(@T,@Index,1) 
      SET @IsDigit = 0 
     END 
     SET @Index = @Index + 1 
    END 
    RETURN @R 
END 

Select Member_ID, dbo.f(Colors) 
From YourTable 
+0

如果顏色是食品染料會怎麼樣:'1)紅色2)藍色湖40 3)紅色湖5'? – mdisibio

+0

@mdisibio。請參閱我的編輯。 –

+0

我在第一條評論中很幽默,但是,當你申請你的陳述時,兩位數字會發生什麼? '10)紅色11)藍色12)綠色' – mdisibio

1

如果Numbers stored in sequence [1), 2), 3)...]你可以像下面

DECLARE @Color VARCHAR(1000) = '1) Red 2) Blue 3) Green' 
DECLARE @Count INT = 1 
DECLARE @Total INT = LEN(@Color) - LEN(REPLACE(@Color,') ',')')) -- Get Total Colors 
-- Loop 
WHILE @Count <= @Total 
BEGIN 
    -- Adding '#' 
    SET @Color = REPLACE(' ' + LTRIM(@Color),' ' + CAST(@Count AS VARCHAR) + ')', ' #' + CAST(@Count AS VARCHAR) + ')') 
    SET @Count = @Count + 1 
END 

而且你可以在更新表。你可以把它作爲UDF。

2

試試這個使用PATINDEX()STUFF()CTE和遞歸查詢(Fiddle Demo):

--//Sample data 
DECLARE @T TABLE (MEMBER_ID INT, COLOR VARCHAR(100)) 

INSERT @T (MEMBER_ID, COLOR) 
VALUES (1, '1) Red 2) Blue 3) Green'), (2, '1) Yellow 2) Black 3) Orange') 


--//Replace @T with your table name 
;WITH CTE AS 
(
    SELECT MEMBER_ID, STUFF(COLOR, PATINDEX('%[0-9][)][ ]%', COLOR), 0, '#') COLOR, 1 NUMBER 
    FROM @T 
    UNION ALL 
    SELECT CTE.MEMBER_ID, STUFF(CTE.COLOR, PATINDEX('%[^#][0-9][)][ ]%', CTE.COLOR) + 1, 0, '#'), NUMBER + 1 
    FROM CTE JOIN @T T 
     ON CTE.MEMBER_ID = T.MEMBER_ID 
    WHERE PATINDEX('%[^#][0-9][)][ ]%', CTE.COLOR) > 0 
), 
CTE2 AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY MEMBER_ID ORDER BY NUMBER DESC) rn 
    FROM CTE 
) 
SELECT MEMBER_ID,COLOR FROM CTE2 WHERE RN = 1 

結果:

| MEMBER_ID | COLOR       | 
|-----------|---------------------------------| 
|   1 | #1) Red #2) Blue #3) Green  | 
|   2 | #1) Yellow #2) Black #3) Orange | 
1

這裏是一個可行的函數:

create function doColors(@input varchar(max)) 
returns varchar(max) 
as 
begin 
    declare @parenIndex int 
    declare @numIndex int = 1 
    select @parenIndex = CHARINDEX(')', @input, 0) 

    while @parenIndex > 0 
    begin 
     set @numIndex = 1 
     while isnumeric(SUBSTRING(@input, @[email protected], 1)) = 1 
     begin 
      set @numindex = @numIndex + 1 
     end 
     if @numIndex > 1 and SUBSTRING(@input, @parenIndex-(@numIndex), 1) = ' ' 
     begin 
      set @input = stuff(@input, @parenIndex-(@numIndex-1), 0, '#') 
     end 
     select @parenIndex = CHARINDEX(')', @input, @parenIndex+2) 
    end 
    return @input 
end 

它基本上找到了parenthesi然後向後查找數字,直到找不到更多數字,然後插入#。它適用於任何數量的顏色,並處理顏色名稱中的數字,圓括號和#等邊緣情況。

1) Red 12) 33 Orange 144) Pink 147) Purple #12 150) Turquoise (light blue) 1024) Brown 
1) Mauve 2) Perrywinkle (13) 3) Black (#12) 

成爲

#1) Red #12) 33 Orange #144) Pink #147) Purple #12 #150) Turquoise (light blue) #1024) Brown 
#1) Mauve #2) Perrywinkle (13) #3) Black (#12) 

SQL Fiddle

相關問題