Я хочу вставить набор значений в заданную строку в указанных положениях. Я не мог найти существующее решение для этого, поэтому я создал следующий запрос, который делает это. Мне интересно, есть ли способ упростить его, особенно часть, которая запрашивает cte и создает NewString. Кроме того, есть ли способ построить рекурсию cte без привлечения столбца ID? Идентификатор (и остальное), кажется, работает нормально, просто интересно, можно ли его настроить, чтобы сделать его более органичным/элегантным или если есть лучшее решение в целом. Различные группы действительно предназначены только для тестирования; каждая группа соответствует возможному сценарию положения вставки. Таким образом, при использовании я не буду участвовать в группах.SQL Server: вставка строки по положению
declare
@String varchar(200),
@StringLen int,
@GroupID int,
@PositionMax int
declare @Chars table (
ID int identity,
GroupID int,
Position int,
Value varchar(20)
)
select
@String = 'abcde',
@StringLen = len(@String),
@GroupID = 1
--Affix
--[P]refix
--[I]nfix
--[S]uffix
insert @Chars
select
GroupID,
Position,
Value
from (
values
(1, 0, 'X'), --P
(2, 2, 'Y'), --I
(3, 5, 'Z'), --S
(4, 0, 'X'), --P
(4, 2, 'Y'), --I
(5, 2, 'Y'), --I
(5, 5, 'Z'), --S
(6, 0, 'X'), --P
(6, 5, 'Z'), --S
(7, 0, 'X'), --P
(7, 2, 'Y'), --I
(7, 5, 'Z'), --S
(8, 2, 'Y1'), --I
(8, 4, 'Y2'), --I
(9, 0, 'X'), --P
(9, 2, 'Y1'), --I
(9, 4, 'Y2'), --I
(10, 2, 'Y1'), --I
(10, 4, 'Y2'), --I
(10, 5, 'Z'), --S
(11, 0, 'X'), --P
(11, 2, 'Y1'), --I
(11, 4, 'Y2'), --I
(11, 5, 'Z') --S
) as T(GroupID, Position, Value)
order by GroupID, Position
;with cte (
ID,
GroupID,
LeftString,
Value,
RightString,
Position
) as (
select
ID,
GroupID,
LeftString,
Value,
RightString,
Position
from (
select
row_number() over (partition by GroupID order by ID) as RowNumber,
ID,
GroupID,
cast(left(@String, Position) as varchar(200)) as LeftString,
Value,
cast(right(@String, @StringLen - Position) as varchar(200)) as RightString,
Position
from @Chars
) as C
where RowNumber = 1
union all
select
vc.ID,
vc.GroupID,
cast(left(RightString, vc.Position - cte.Position) as varchar(200)) as LeftString,
vc.Value,
cast(right(RightString, @StringLen - vc.Position) as varchar(200)) as RightString,
vc.Position
from @Chars vc
join cte cte
on cte.GroupID = vc.GroupID
and cte.ID + 1 = vc.ID
)
select
GroupID,
case
when LSLenSumMax < @StringLen
then NewString + RightString
else NewString
end as NewString
from (
select
GroupID,
max(LSLenSum) as LSLenSumMax,
RightString,
stuff((
select
LeftString + Value
from cte cte
where cte.GroupID = cteLR.GroupID
for xml path(''), type
).value('(./text())[1]', 'varchar(max)'), 1, 0, '') as NewString
from (
select
GroupID,
(select sum(len(LeftString)) from cte cteL where cteL.groupID = cte.groupID) as LSLenSum,
(select top 1 RightString from cte cteR where cteR.groupID = cte.groupID order by cteR.ID desc) as RightString
from cte cte
) as cteLR
group by
GroupID,
RightString
) as C
order by GroupID
Я не знаю пути, но пару дней назад я нашел действительно классную статью о n-граммах, которая могла бы помочь: http://www.sqlservercentral.com/articles/Tally+Table/142316/ – vercelli