问题
I have one question: in sql server, how to replace the 2nd occurrence of the string happy to the string new, otherwise keep as it is(same).
Table:
CREATE TABLE [dbo].[stringrep](
[name] [varchar](100) NULL,
[id] [int] NULL
)
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy happy year', 1)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'very happy new year', 2)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy new year hello', 3)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy happy year', 4)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'heloo year happy', 5)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy happy happy year', 6)
GO
based on above data I want output like below:
id | Name
1 | happy new year
2 | very happy new year
3 | happy new year hello
4 | happy new year
5 | heloo year happy
6 |happy new happy year
I tried the query below :
SELECT replace ( name ,'happy happy year' ,'happy new year')afterreplacename,
replace ( name, substring ('happy happy year' ,6,6) ,' new')anotherway
,name ,[id]
FROM [test].[dbo].[stringrep]
The above query does not give the expected result.
Please tell me how to achive this task in sql server .
回答1:
I managed to come up with the following query. The replacement logic only targets data having happy occurring at least two times. If so, then we find the index of the second occurrence of happy, and then STUFF in new as a replacement.
SELECT
data,
CASE WHEN LEN(REPLACE(data, 'happy', '')) < LEN(data) - 6
THEN STUFF(data,
CHARINDEX('happy', data, CHARINDEX('happy', data) + 1),
5,
'new')
ELSE data END AS new_data
FROM yourTable;
Demo
Note that this solution is robust to the two (or more) occurrences of happy being anywhere in the string. See the last row of the sample data for this edge case.
We would rather like to use regex here, and maybe you question could be answered with a one-liner. But, SQL Server does not have good native regex support, forcing us to use the base string functions instead.
回答2:
I find the second occurrence happy, if there is only one occurrence happy returns the original string, otherwise the string is split. I am get what is before the second occurrence of the word happy + new + everything that was after the second occurrence of the word happy.
SELECT
CASE
WHEN CHARINDEX('happy', [name], (CHARINDEX('happy', [name])+1)) <> 0 THEN
SUBSTRING([name],0,CHARINDEX('happy', [name], (CHARINDEX('happy', [name])+1)))
+ 'new '
+ SUBSTRING([name],CHARINDEX('happy', [name], (CHARINDEX('happy',
[name])+1))+5,100)
ELSE [name]
END
FROM [dbo].[stringrep]
Output:
happy new year
very happy new year
happy new year hello
happy new year
heloo year happy
happy new happy year
回答3:
That would be simple RegEx if... SQL Server supports RegExes. I recommend using other tool to replace values - any major programming language with database access and RegEx support. If this is frequent operation, use CLR Functions. And then, remember:
To iterate is human, to recurse divine
This is why:
WITH Splitter AS
(
SELECT id, 1 num, SUBSTRING(name, 1, charindex(' ',name)-1) Word, SUBSTRING(name, charindex(' ',name), LEN(name)) Rest FROM stringrep
UNION ALL
SELECT
id,
num+1 num,
CASE WHEN charindex(' ',Rest)=1 THEN ' '
WHEN charindex(' ',Rest)=0 THEN Rest
ELSE SUBSTRING(Rest, 1, charindex(' ',Rest)-1) END Word,
CASE WHEN charindex(' ',Rest)=1 THEN SUBSTRING(Rest, 2, LEN(Rest))
WHEN charindex(' ',Rest)=0 THEN ''
ELSE SUBSTRING(Rest, charindex(' ',Rest), LEN(Rest)) END Rest
FROM Splitter
WHERE LEN(rest)>0
), Replacer AS
(
SELECT S1.id, S1.num, CASE WHEN LastNotSpace='happy' AND Word='happy' AND (LastLastNotSpace IS NULL OR LastLastNotSpace!='happy') THEN 'new' ELSE Word END NewWord
FROM Splitter S1
LEFT JOIN (SELECT id,num,LAG(Word) OVER (PARTITION BY id ORDER BY num) LastNotSpace, LAG(Word,2) OVER (PARTITION BY id ORDER BY num) LastLastNotSpace FROM Splitter WHERE Word!=' ') T ON S1.id=T.id AND S1.num=T.num
), Joiner AS
(
SELECT id, num, CAST(NewWord AS nvarchar(MAX)) Joined FROM Replacer WHERE num=1
UNION ALL
SELECT S.id, S.num, J.Joined+S.NewWord Joined FROM Joiner J
JOIN Replacer S ON J.id=S.id AND J.num+1=S.num
), Filter AS
(
SELECT id, Joined FROM (
SELECT id, num, Joined, ROW_NUMBER() OVER (PARTITION BY id ORDER BY num DESC) Lev FROM Joiner
) T WHERE Lev=1
)
SELECT * FROM Filter
回答4:
Try this:
select [name], id,
case when secondIndex > 0 then stuff([name], secondIndex, 5, 'new') else [name] end newName
from (
select [name], id, charindex('happy', [name], charindex('happy', [name]) + 1) secondIndex
from #stringrep
) a
来源:https://stackoverflow.com/questions/52000988/how-to-replace-second-position-string-with-new-in-sql-server