Вы можете использовать следующую UDF ( встроенную функцию вместо скалярной )
CREATE FUNCTION dbo.INSTR
(
@str VARCHAR(8000),
@Substr VARCHAR(1000),
@start INT ,
@Occurance INT
)
RETURNS TABLE
AS
RETURN
WITH Tally (n) AS
(
SELECT TOP (LEN(@str)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n)
)
, Find_N_STR as
(
SELECT
CASE WHEN DENSE_RANK() OVER(PARTITION BY @Substr ORDER BY (CHARINDEX(@Substr ,@STR ,N))) = @Occurance
THEN MAX(N-@start +1) OVER (PARTITION BY CHARINDEX(@Substr ,@STR ,N) )
ELSE 0
END [Loc]
FROM Tally
WHERE CHARINDEX(@Substr ,@STR ,N) > 0
)
SELECT Loc= MAX(Loc)
FROM Find_N_STR
WHERE Loc > 0
Как использовать:
declare @T table
(
Name_Level_Class_Section varchar(25)
)
insert into @T values
('Jacky_1_B2_23'),
('Johnhy_1_B2_24'),
('Peter_2_A5_3')
select t.Name_Level_Class_Section , l.Loc
from @t t
cross apply dbo.INSTR (t.Name_Level_Class_Section, '_',1,2) l