Вы можете использовать рекурсивное решение (и действительно, это, вероятно, единственный жизнеспособный ответ). Вы бы, вероятно, сохранили обработку, если бы у вас был предопределенный порядок (потому что на данный момент единственный способ, которым я могу думать, это объединение текста).
Вот общее решение, которое должно дать вам необходимые результаты.
Обратите внимание, что это было написано и запущено в DB2 (iSeries) - вам может потребоваться настроить его для SQL Server.
WITH Combined(productId, options, combination, level) as (
SELECT productId, optionName, skuModifier, 1
FROM #Modifiers
UNION ALL
SELECT a.productId, a.options || b.optionName,
a.combination || b.skuModifier, a.level + 1
FROM Combined as a
JOIN #Modifiers as b
ON b.productId = a.productId
AND a.options not like ('%' || b.optionName || '%')),
Option_Count(productId, count) as (SELECT productId, COUNT(DISTINCT optionName)
FROM #Modifiers
GROUP BY productId)
SELECT a.sku || COALESCE(b.combination, '')
FROM #Base as a
LEFT JOIN (Combined as b
JOIN Option_Count as c
ON c.productId = b.productId
AND c.count = b.level)
ON b.productId = a.productId)
Что дает:
MARIN17R
MARIN15R
MARIN19R
MARIN20R
MARIN17G
MARIN15G
MARIN19G
MARIN20G
MARIN17B
MARIN15B
MARIN19B
MARIN20B
MARINR17
MARING17
MARINB17
MARINR15
MARING15
MARINB15
MARINR19
MARING19
MARINB19
MARINR20
MARING20
MARINB20
Лично я думаю, что я попытался бы установить какой-то порядок - это, по крайней мере, позволило бы вам избавиться от работы с optionName
(хотя в этом случае вы можете дополнительно нормализовать таблицы).
Обратите внимание, что CTE Option_Count
используется для ограничения результатов комбинациями «полной длины» - перестановками, в которых используются все параметры, а не только некоторые из них.