-
Tom Phillips 17,631 Reputation points
2021-09-29T15:11:28.937+00:00 select t.[Level], t.[Condition], STRING_AGG(t1.ID,',') WITHIN GROUP (ORDER BY t1.ID) AS TName from #temp t CROSS APPLY string_split(t.TName,',') s INNER JOIN #temp1 t1 ON t1.tags = s.[value] GROUP BY t.[Level], t.[Condition] ORDER BY t.[Level], t.[Condition]
Two solutions depending on what you mean by "exact result".
If you don't care about the order of the tags value, for example, if is it OK if your result reversed the tags on Level 2 so it looked like
2 L2 103,102
If that's OK, then you can do
Select t.Level, t.Condition, String_Agg(t1.ID, ',')
From #temp t
Cross Apply String_Split(t.TName, ',') s
Inner Join #temp1 t1 On s.value = t1.Tags
Group By t.Level, t.Condition
Order By Level;
But if the strings must always show the tags in the order from TNAME, then you will need to create a split function which preserves the order of the items. The builtin function String_Split used in the above doesn't ALWAYS do that. So then you solution would look like, first create the user function
CREATE FUNCTION dbo.Split (@DelimitedString nvarchar(max), @Delimiter nvarchar(max))
RETURNS table
/* Use Option(MaxRecursion 0) in queries that call this function if
there can be more than 99 delimited values in @DelimitedString */
AS
RETURN (
WITH Pieces (ID, start, stop) AS (
SELECT CAST(1 AS bigint), CAST(1 AS bigint), CAST(CHARINDEX(@Delimiter, @DelimitedString) AS bigint)
UNION ALL
SELECT ID + 1, CAST(stop + DATALENGTH(@Delimiter)/2 As bigint), CAST(CHARINDEX(@Delimiter, @DelimitedString, stop + DATALENGTH(@Delimiter)/2) AS bigint)
FROM Pieces
WHERE stop > 0
)
SELECT ID,
SUBSTRING(@DelimitedString, start, CASE WHEN stop > 0 THEN stop-start ELSE LEN(@DelimitedString) END) AS Element
FROM Pieces
)
GO
Then you can do
Select t.Level, t.Condition, String_Agg(t1.ID, ',') Within Group (Order By s.ID)
From #temp t
Cross Apply dbo.Split(TName, ',') s
Inner Join #temp1 t1 On s.Element = t1.Tags
Group By t.Level, t.Condition
Order By Level;
Tom