Поскольку вы используете старую версию сервера SQL, у вас нет доступа к STRING_SPLIT
или STRING_AGG
. Первый, однако, здесь не особенно полезен, так как Microsoft все еще не реализовали порядковые позиции в функции, и она поддерживает только разделитель одного символа.
Вместо этого я собираюсь использовать DelimitedSplit8k_LEAD
, который поддерживает порядковые позиции. К сожалению, он также поддерживает только разделитель одного символа, поэтому я заменил двойной разделитель точки с запятой (;;
) на трубу (|
); так как я предполагаю, что они не появятся в ваших данных.
2012 также не имеет TRIM
, поэтому вам придется использовать RTRIM
и LTRIM
для обрезки значений.
Наконец, вы можете использовать «старый» метод FOR XML PATH
для «повторного агрегирования» строки:
WITH Splits AS(
SELECT t.id,
t.attr,
DS.ItemNumber,
NULLIF(LTRIM(RTRIM(DS.Item)),'NULL') AS Item,
ROW_NUMBER() OVER (PARTITION BY T.id, LTRIM(RTRIM(NULLIF(DS.Item,'NULL'))) ORDER BY DS.ItemNumber) AS RN
FROM dbo.test t
CROSS APPLY dbo.DelimitedSplit8K_LEAD(REPLACE(t.val,';;','|'),'|') DS) --DelimitedSplit8K only supports a one character splitter
SELECT t.ID,
t.attr,
STUFF((SELECT ';;' + S.Item
FROM Splits S
WHERE S.ID = t.ID
AND S.RN = 1
ORDER BY S.ItemNumber
FOR XML PATH(''),TYPE).value('.','varchar(MAX)'),1,2,'') AS NewVal
FROM dbo.test t;
Редактировать: Забыли о дубликатах. Я использую ROW_NUMBER
в CTE для нумерации значений, а затем фильтрую в WHERE
подзапроса FOR XML PATH
. DISTINCT
и GROUP BY
не будут работать там, так как тогда ItemNumber
не будет разрешено использовать в ORDER BY
.