I'm sorry to say but the currently accepted answer (by Sami) is wrong.
The problem with this answer is that it use ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
to get the order of the items in the comma delimited string, but since the order by
is done on select null
, what actually happens is that the row_number
will assign the numbers in an arbitrary order - that may or may not match the order of the strings in the source string.
For more information, read Conor Cunningham's No Seatbelt – Expecting Order without ORDER BY.
If your split UDF returns a table with two columns, where one contains the substring and the other contains it's index, like Jeff Moden's DelimitedSplit8K, then simply use the ItemNumber
(or equivalent) column for the order by
. If it only returns a single column containing the substrings, you can use this a nice trick I've learned from Aaron Bertrand's Solve old problems with SQL Server’s new STRING_AGG and STRING_SPLIT functions - it will guarantee to return the correct order of the substrings as long as they are unique.
A simple change on Sami's answer will give you correct results as long as the substrings are unique within the comma delimited string - Instead of ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
, use CHARINDEX(',' + Value + ',', ',' + @Ids + ',')
, which will return the index of each substring inside the comma delimited string:
CREATE TABLE T(
ID INT,
SomeValue VARCHAR(45)
);
INSERT INTO T VALUES
(1, 'One'),
(2, 'Two'),
(3, 'Three'),
(4, 'Four'),
(5, 'Five');
DECLARE @IDs VARCHAR(200) = '3,5,2';
SELECT T.*
FROM T
INNER JOIN
(SELECT Value,
CHARINDEX(',' + Value + ',', ',' + @Ids + ',') AS Seq
FROM dbo.Split(@Ids, ',')
) TT
ON T.ID = TT.Value
ORDER BY TT.Seq;