我有一張表包含歷史表中的這樣的數據。特定字符串組之前的東西或插入字符串
MEMBER_ID COLORS
1 1) Red 2) Blue 3) Green
我需要修改或選擇數據,以便結果集看起來像這樣。
MEMBER_ID COLORS
1 #1) Red #2) Blue #3) Green
簡而言之,在數字和右括號之前插入英鎊。
我試過使用CHARINDEX
,但我試過的東西沒有工作。
我有一張表包含歷史表中的這樣的數據。特定字符串組之前的東西或插入字符串
MEMBER_ID COLORS
1 1) Red 2) Blue 3) Green
我需要修改或選擇數據,以便結果集看起來像這樣。
MEMBER_ID COLORS
1 #1) Red #2) Blue #3) Green
簡而言之,在數字和右括號之前插入英鎊。
我試過使用CHARINDEX
,但我試過的東西沒有工作。
假設MS SQL Server ...最簡單的方法是: 選擇MEMBER_ID,REPLACE(REPLACE(REPLACE(COLORS,'1','#1'),'2','#2'),'3' ,'#3')AS顏色
是的是SQL Server,問題是,你不知道顏色的數量。所以這些數字是不固定的。它可能是3或10.在這種情況下,替換不會像你所建議的那樣工作。 – Asynchronous
你可以做到最大數量的顏色,你會有。如果你不會有超過10種顏色,只需10'REPLACE's。如果柱子的顏色少於10種,它不會造成任何傷害。它不是很優雅,如果你有數百種顏色,它會吸引人,但如果你只有1到9之間,這可能是最簡單的解決方案。 – Jerrad
當你申請你的陳述時,兩位數字會發生什麼? '10)紅色11)藍色12)綠色' – mdisibio
我不確定您的數據有多可預測性,所以我會提供一個建議,並且您可以使用類似的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
我已經更新了我的答案,不要求索引先於空格。它只需要一個或兩個數字後跟一個parens。再次,這一切都取決於確切的要求。 – mdisibio
您可以使用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
如果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。
試試這個使用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 |
這裏是一個可行的函數:
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)
將它永遠是個位數的? –
是的,大部分在1到9之間。 – Asynchronous
我在想你可以根據以下字符串來分割字符串: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 –