我在历史表中有一个包含这样数据的表。
MEMBER_ID COLORS
1 1) Red 2) Blue 3) Green
我需要修改或选择数据,以便结果集看起来像这样。
MEMBER_ID COLORS
1 #1) Red #2) Blue #3) Green
简而言之,在数字和右括号之前插入英镑。
我尝试使用CHARINDEX
,但我尝试过的功能无效。
答案 0 :(得分:2)
我不确定您的数据有多可预测,因此我会提供一个建议,您可以使用类似的PATINDEX
s扩展它以适用于任何其他极端情况。
我在此建议中的假设是每个文本可能以任何单个数字开头(例如" 1)" )没有前面的空格,你只有一个或两个数字的索引(只是扩展我对更高指数的建议),并且唯一要转换的数字是那些后面跟着的数字。
-- 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
答案 1 :(得分: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
答案 2 :(得分: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 |
答案 3 :(得分:1)
假设MS SQL Server ......最简单的方法是: 选择MEMBER_ID,REPLACE(REPLACE(替换(颜色,'1','#1'),'2','#2'),'3','#3')AS COLORS
答案 4 :(得分: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。
答案 5 :(得分: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, @parenIndex-@numIndex, 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
它基本上找到括号,然后向后查找数字,直到它找不到为止,然后插入#
。它适用于任意数量的颜色,并处理颜色名称中的数字,圆括号和#
等边缘情况。
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)