用TSQL求子串在父串中出現的次數

2021-05-04 07:15:24 字數 2990 閱讀 1587

導言

由於sql server本身沒提供計算乙個字串在另乙個字串重複次數的函式,大家按照自己的思路使用自定義函式實現了該功能,並在網上傳播。我閱讀了同事從網上獲取的該函式的乙個版本後,便發現該函式存在乙個明顯的邏輯錯誤。為了進一步確認這個問題,我在google上搜尋相關關鍵字,發現該功能多數的實現思路一致,但大多數都存在這個共同的邏輯錯誤。可見從網路上獲取的一些資源,可以作為參考,但要在實際需求中能夠應用,是需要仔細檢查的。

功能實現

常見方法

set ansi_nulls on

goset quoted_identifier on

go --描述:利用迴圈得到乙個字串在另乙個字串中出現的次數

--demo:

-- select dbo.f_getcharcount_false('df ththth','tht')

create function [dbo].[f_getcharcount_false](

@str varchar(8000),

@chr varchar(8000)

) returns int

asbegin

declare @re int,@i int

select @re=0,@i=charindex(@chr,@str)+1

while @i>1

select @re=@re+1

,@str=substring(@str,@i,8000)

,@i=charindex(@chr,@str)+1

return(@re)

end上面的函式設計思路是迴圈截斷源字串,通過計算截斷的次數來獲取子字串出現的重複數。思路當然是可行的,但是在它截斷的時候,起點是@i=charindex(@chr,@str)+1,這裡就是錯誤的起因。以我給出的demo來講,**如下:

select dbo.f_getcharcount_false('df ththth','tht')

結果為2,其實明顯,正確的結果是1。因為上述函式的截斷內容只有「t」,而後面的「ht」會被繼續使用,導致「t」與後面的「ht」組合,結果計數多了一次。正確的擷取位置應該從子串的位置結束處開始,就是從「tht」後面開始。

既然思路正確,那麼我們就修改上述**中的錯誤,修改後的**如下:第1頁:null 第2頁:null 第3頁:null 。

set ansi_nulls on

goset quoted_identifier on

go --描述:利用迴圈得到乙個字串在另乙個字串中出現的次數

--demo:

--  select dbo.f_getcharcount_true('df ththth','tht')

create function [dbo].[f_getcharcount_true](

@str varchar(8000),

@chr varchar(8000)

) returns int

asbegin

declare @re int,@i int

select @re=0,@i=charindex(@chr,@str)+1

while @i>1

select @re=@re+1

,@str=substring(@str,@i-1+len(@chr),8000)

,@i=charindex(@chr,@str)+1

return(@re)

end當然,截斷字串很多人喜歡用stuff填充空字元,但網上流傳的該版本,用stuff函式實現截斷操作的,多數也是存在這個截斷位置錯誤的。

優化的方法

上面講的只是在網路上流傳最廣泛的方法,那麼想要精煉**,尋找更便捷和高效的方法也是可行。下面再介紹兩種較便捷的實現方式。

《方法一》

set ansi_nulls on

goset quoted_identifier on

go /*

描述:利用字串長度計算字元出現次數

demo:

select dbo.f_get_char_repeat_count('df ththth','tht')

*/create function [dbo].[f_get_char_repeat_count]

(@str varchar(8000),

@substr varchar(8000)

)returns int

begin

return (len(@str)-len(replace(@str,@substr,'')))/len(@substr)

end第1頁:null 第2頁:null 第3頁:null 。

《方法二》

set ansi_nulls on

goset quoted_identifier on

go /*

描述:利用長度差值求重複次數

demo:

select fn_get_char_repeat_count_by_add_char('ahahaahde','ah')

*/create function [dbo].[fn_get_char_repeat_count_by_add_char](

@str varchar(8000),--父串

@chr varchar(8000) --子串

) returns int

asbegin

return(len(replace(@str,@chr,@chr+' '))-len(@str))

end上面的《方法一》是用空字元替換父字串中出現的子串,用剩餘字串的長度與子字串的長度求商;《方法二》是把為父字串中出現子字串的地方都增加個空格,用替換後的父字串長度減去原父字串的長度。

本文**:http://www.techrss.cn/html/2008/03-30/78902.htm

統計子串在主串中出現的次數

思路 定義兩個指標p,q p指向主串首位址,q指向子串首位址。如果對應的字元相等,那麼 p,q,即兩個指標都向後移乙個單位再繼續比較 p和 q,否則q回到子串的首位址,只把指標p向後移動乙個單位。依次類推,如果 q 0 說明子串已經終止,子串在主串中出現的次數加1,直到主串終止為止。includei...

java獲取子串在整串中出現的次數

方法一 這是bxdteacher的方法 package stringclass 2,乙個子串在整串 現的次數。nbaernbatynbauinbaopnba 思路 1,要找的子串是否存在,如果存在獲取其出現的位置。這個可以使用indexof完成。2,如果找到了,那麼就記錄出現的位置並在剩餘的字串中繼...

求子串在母串中最後一次出現的位址

給定程式中函式fun的功能是 求出在字串中最後一次出現的子字串的位址,通過函式值返回,在主函式中輸出從此位址開始的字串 若未找到,則函式值為null。char fun char s,char t 其中 s 和 t 是使用者傳入的引數。函式求 t 指標所指的字串在s指標所指的字串中最後一次出現的位址,...