遅くなって申し訳ありませんが、これを拡張したい人のために物事を簡単にしたいと思います。私はこれらの各実装を見て、私にとって最良と思われる実装(Aaron Bertrand)を採用し、それを簡略化しました。これで「テンプレート」ができました。賢く使ってください。
CREATE FUNCTION dbo.CHARINDICES (
@search_expression NVARCHAR(4000),
@expression_to_be_searched NVARCHAR(MAX)
) RETURNS TABLE AS RETURN (
WITH tally AS (
SELECT Number = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects)
SELECT DISTINCT n = subIdx -- (4) if we don't perform distinct we'll get result for each searched substring, and we don't want that
FROM
tally
CROSS APPLY (SELECT subIdx = CHARINDEX(@search_expression, @expression_to_be_searched, Number)) x -- (2) subIdx is found in the rest of the substring
WHERE
Number BETWEEN 1 AND LEN(@expression_to_be_searched) -- (1) run for each substring once
AND SubIdx != 0 -- (3) we care only about the indexes we've found, 0 stands for "not found"
)
SELECT CHARINDEX('C', 'BACBABCBABBCBACBBABC')
SELECT * FROM dbo.CHARINDICES('C', 'BACBABCBABBCBACBBABC')
参考として-PATINDEX()を展開するなど、これから他の動作を派生させることができます。
CREATE FUNCTION dbo.PATINDICES (
@search_expression NVARCHAR(4000) = '%[cS]%',
@expression_to_be_searched NVARCHAR(MAX) = 'W3Schools.com'
) RETURNS TABLE AS RETURN (
WITH tally AS (
SELECT num = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects)
SELECT DISTINCT n = subIdx + num - 1
FROM
tally
CROSS APPLY (SELECT numRev = LEN(@expression_to_be_searched) - num + 1) x
CROSS APPLY (SELECT subExp = RIGHT(@expression_to_be_searched, numRev)) y
CROSS APPLY (SELECT subIdx = PATINDEX(@search_expression, subExp)) z
WHERE
num BETWEEN 1 AND LEN(@expression_to_be_searched)
AND SubIdx != 0
)
SELECT PATINDEX('%[cS]%', 'W3Schools.com')
SELECT * FROM dbo.PATINDICES('%[cS]%', 'W3Schools.com')
1
0と1のみを含む文字列を検索する2つの関数を作成しました。私はあなたのソリューションと@ aaron-bertrandを使用しましたが、同じ結果と同じパフォーマンスが得られました。どの解決策が良いでしょうか?