snippetsqlModerate
How to find all positions of a string within another string
Viewed 0 times
positionshowallwithinanotherfindstring
Problem
How can I find all the positions with
This returns
patindex in a table or variable?declare @name nvarchar(max)
set @name ='ali reza dar yek shabe barani ba yek '
+ 'dokhtare khoshkel be disco raft va ali baraye'
+ ' 1 saat anja bud va sepas... ali...'
select patindex('%ali%',@name) as posThis returns
1 but I want all results, e.g.:pos
===
1
74
113Solution
I think this will be slightly more efficient than the looping method you've chosen (some evidence here), and definitely more efficient than the recursive CTE:
Sample usage:
Results:
If your strings will be longer than 2K then use sys.all_columns instead of sys.all_objects. If longer than 8K then add a cross join.
CREATE FUNCTION dbo.FindPatternLocation
(
@string NVARCHAR(MAX),
@term NVARCHAR(255)
)
RETURNS TABLE
AS
RETURN
(
SELECT pos = Number - LEN(@term)
FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@string, Number,
CHARINDEX(@term, @string + @term, Number) - Number)))
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects) AS n(Number)
WHERE Number > 1 AND Number <= CONVERT(INT, LEN(@string)+1)
AND SUBSTRING(@term + @string, Number, LEN(@term)) = @term
) AS y);Sample usage:
DECLARE @name NVARCHAR(MAX);
SET @name = N'ali reza dar yek shabe barani ba yek'
+ ' dokhtare khoshkel be disco raft va ali baraye '
+ '1 saat anja bud va sepas... ali...';
SELECT pos FROM dbo.FindPatternLocation(@name, 'ali');Results:
pos
---
1
74
113If your strings will be longer than 2K then use sys.all_columns instead of sys.all_objects. If longer than 8K then add a cross join.
Code Snippets
CREATE FUNCTION dbo.FindPatternLocation
(
@string NVARCHAR(MAX),
@term NVARCHAR(255)
)
RETURNS TABLE
AS
RETURN
(
SELECT pos = Number - LEN(@term)
FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@string, Number,
CHARINDEX(@term, @string + @term, Number) - Number)))
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects) AS n(Number)
WHERE Number > 1 AND Number <= CONVERT(INT, LEN(@string)+1)
AND SUBSTRING(@term + @string, Number, LEN(@term)) = @term
) AS y);DECLARE @name NVARCHAR(MAX);
SET @name = N'ali reza dar yek shabe barani ba yek'
+ ' dokhtare khoshkel be disco raft va ali baraye '
+ '1 saat anja bud va sepas... ali...';
SELECT pos FROM dbo.FindPatternLocation(@name, 'ali');pos
---
1
74
113Context
StackExchange Database Administrators Q#41961, answer score: 18
Revisions (0)
No revisions yet.