Reputation: 815
declare @RuleTable table (RuleId int, Pattern varchar(max) , Frequency int )
insert into @RuleTable
select 1, '3,5,4,6' , 2
SELECT
ROW_NUMBER() OVER(PARTITION BY items ORDER BY (select 1)) - 1 AS Id,
RuleId,
items AS ShiftId
FROM @RuleTable
CROSS APPLY SplitNew(REPLICATE(REPLACE(','+ LTRIM(RTRIM(Pattern)) +',',',0,',',') +',', Frequency ), ',') as ss
current output is this...
but in expected output I should not lost the order of the comma separated string
Means Output should be like
ShiftId
3
3
5
5
4
4
6
6
Note: Frequency means how many times each shiftid from comma separated string should repeat.
Upvotes: 0
Views: 277
Reputation: 1269583
You can find the first position of a value in the string:
SELECT ss.seqnum - 1 AS Id, RuleId, items AS ShiftId
FROM @RuleTable CROSS APPLY
(SELECT ss.*,
ROW_NUMBER() OVER (ORDER BY CHARINDEX(',' + Frequency + ',', ',' + Pattern + ',')) as seqnum
FROM SplitNew(REPLICATE(REPLACE(','+ LTRIM(RTRIM(Pattern)) +',', ',0,', ',') +',', Frequency ), ',') as ss
) ss;
I don't understand your search -- but then you are using an undocumented function. This would more typically be written as:
SELECT (ss.seqnum - 1) as Id, rt.RuleId, ss.value as ShiftId
FROM @RuleTable rt CROSS APPLY
(SELECT ss.*,
ROW_NUMBER() OVER (ORDER BY CHARINDEX(',' + rt.Frequency + ',', ',' + rt.Pattern + ',')) as seqnum
FROM string_split(pattern, ',') ss
) ss;
Note that this uses the built-in string_split()
function. There is no need for a user-defined function with this method.
Upvotes: 1
Reputation: 95554
It appears you have a couple of problems here. Firstly, I would guess that your splitter (that we are missing the definition of) does not observe/retain ordinal position. Therefore we need to use a splitter than does. I recommend delimitedsplit8k_LEAD
.
Then we need to look at how you repeat the rows. Using REPLICATE
like that isn't the right approach. You'll be better off with a Tally. I've used an inline one here, and assume Frequency
can't have a value greater than 10
. If it does, use a CTE to create an inline Tally (there are plenty of examples out there on how to do this, and don't use the ones that use an rCTE, because they are slow).
After that, you end up with something like this:
SELECT ROW_NUMBER() OVER (PARTITION BY DS.Item ORDER BY DS.ItemNumber) - 1 AS ID,
RT.RuleId,
DS.Item
FROM @RuleTable RT
CROSS APPLY dbo.DelimitedSplit8K_LEAD(RT.Pattern,',') DS
JOIN (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))V(I) ON RT.Frequency >= V.I
ORDER BY DS.ItemNumber,
V.I;
Upvotes: 2