how to replace second position string with new in sql server

扶醉桌前 提交于 2019-12-10 14:42:21

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!