Хорошо, после некоторого переосмысления я предложу ультимативный, основанный на XML type-safe и sort-safe splitter:
Declare @List varchar(max)='212345, 312345, 145687, 658975, 256987, 365874, 568974, 124578, 125689';
DECLARE @delimiter VARCHAR(10)=', ';
WITH Casted AS
(
SELECT (LEN(@List)-LEN(REPLACE(@List,@delimiter,'')))/LEN(REPLACE(@delimiter,' ','.')) + 1 AS ElementCount
,CAST('<x>' + REPLACE((SELECT @List AS [*] FOR XML PATH('')),@delimiter,'</x><x>')+'</x>' AS XML) AS ListXml
)
,Tally(Nmbr) As
(
SELECT TOP((SELECT ElementCount FROM Casted)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values v1 CROSS JOIN master..spt_values v2
)
SELECT Tally.Nmbr AS Position
,(SELECT ListXml.value('(/x[sql:column("Tally.Nmbr")])[1]','int') FROM Casted) AS Item
FROM Tally;
Хитростьэто создать список чисел с подходящим номером элемента (таблица чисел была еще лучше) и выбрать элементы в соответствии с их положением.
Подсказка: это довольно медленно ...
ОБНОВЛЕНИЕ: еще лучше:
WITH Casted AS
(
SELECT (LEN(@List)-LEN(REPLACE(@List,@delimiter,'')))/LEN(REPLACE(@delimiter,' ','.')) + 1 AS ElementCount
,CAST('<x>' + REPLACE((SELECT @List AS [*] FOR XML PATH('')),@delimiter,'</x><x>')+'</x>' AS XML)
.query('
for $x in /x
return <x p="{count(/x[. << $x])}">{$x/text()[1]}</x>
') AS ListXml
)
SELECT x.value('@p','int') AS Position
,x.value('text()[1]','int') AS Item
FROM Casted
CROSS APPLY Casted.ListXml.nodes('/x') AS A(x);
Элементы создаются как
<x p="99">TheValue</x>
К сожалению, функция XQuery
position()
недоступна для извлечения Значение.Но вы можете использовать трюк для подсчета всех элементов до данного узла.это плохо масштабируется, так как этот счет должен выполняться снова и снова.Чем больше элементов, тем хуже это идет ...
ОБНОВЛЕНИЕ2: При известном количестве элементов можно использовать это (гораздо лучшая производительность)
Используйте XQuery
для итерации буквально заданного списка:
WITH Casted AS
(
SELECT (LEN(@List)-LEN(REPLACE(@List,@delimiter,'')))/LEN(REPLACE(@delimiter,' ','.')) + 1 AS ElementCount
,CAST('<x>' + REPLACE((SELECT @List AS [*] FOR XML PATH('')),@delimiter,'</x><x>')+'</x>' AS XML)
.query('
for $i in (1,2,3,4,5,6,7,8,9)
return <x p="{$i}">{/x[$i]/text()[1]}</x>
') AS ListXml
)
SELECT x.value('@p','int') AS Position
,x.value('text()[1]','int') AS Item
FROM Casted
CROSS APPLY Casted.ListXml.nodes('/x') AS A(x);