I have a database that I've inherited and need to create a query that generates all possible variations of a SKU. One table has the "base" SKU and the other table has all the SKU modifiers.
Example
Base SKU: MARIN could be modified into
MARINR15 MARINB15 MARING15 MARINR17 MARINB17 MARING17 MARINR19 MARINB19 MARING19 MARINR20 MARINB20 MARING20
Base SKU
ProductID SKU
----------- ---------------
532 MARIN
SKU Modifiers
ProductID OptionName OptionValue SkuModifier
----------- -------------------- ------------------------ -----------
532 Color Red R
532 Color Green G
532 Color Blue B
532 Size 17" 17
532 Size 15" 15
532 Size 19" 19
532 Size 20" 20
You can use a recursive solution (and indeed, this is probably the only viable answer). You'd probably save processing if you had a predifined ordering (because at the moment the only way I can think to do this is text concatenation).
Here is a general solution that should get you your needed results.
Note that this was written and run on DB2 (iSeries) - you may need to adjust it for 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)
Which yields:
MARIN17R
MARIN15R
MARIN19R
MARIN20R
MARIN17G
MARIN15G
MARIN19G
MARIN20G
MARIN17B
MARIN15B
MARIN19B
MARIN20B
MARINR17
MARING17
MARINB17
MARINR15
MARING15
MARINB15
MARINR19
MARING19
MARINB19
MARINR20
MARING20
MARINB20
Personally, though, I think I'd try to get some sort of ordering established - this would at least allow you to knock out dealing with optionName
(although in that case you may want to further normalize the tables).
Please note that the CTE Option_Count
is being used to restrict results to 'full-length' combinations - permutations where all the options are used, rather than just some of them.