Say we have a simple DB-table tab created in MySql with
JavaScript
x
CREATE TABLE `tab` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val` int(11) DEFAULT NULL,
`altval` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
and filled with an examplary set of data:
JavaScript
INSERT INTO tab VALUES(1,1,NULL);
INSERT INTO tab VALUES(2,2,3);
INSERT INTO tab VALUES(3,4,NULL);
INSERT INTO tab VALUES(4,5,6);
Each row has a value val and for id=2,4 an alternative value altval. Is there a way in SQL to retrieve all combinations for abitrary data sets? (The number of combinations is 2 power the number of rows with alternative datasets, here: 4, therefore ‘abitrary’ is of course limited.) For the given example, the result should be: (1,2,4,5),(1,2,4,6),(1,3,4,5),(1,3,4,6)
In a script language like php, I would solve this problem by generating nested for-loops using eval().
Advertisement
Answer
Using recursive CTE:
JavaScript
WITH RECURSIVE cte AS (
-- continuous rn
SELECT CAST(val AS CHAR(11)) val, CAST(altval AS CHAR(11)) AS altval,
ROW_NUMBER() OVER(ORDER BY id) AS rn
FROM tab
), rec AS (
-- anchor
SELECT val AS result, rn
FROM cte
WHERE rn = 1
UNION ALL
SELECT altval AS result, rn
FROM cte
WHERE rn = 1
AND altval IS NOT NULL
UNION ALL
-- recursive part
SELECT CONCAT(rec.result, ',', cte.val), cte.rn
FROM rec
JOIN cte ON cte.rn = rec.rn+1
UNION ALL
SELECT CONCAT(rec.result, ',', cte.altval), cte.rn
FROM rec
JOIN cte ON cte.rn = rec.rn+1
WHERE cte.altval IS NOT NULL
)
SELECT result
FROM rec
WHERE rn = (SELECT COUNT(*) FROM cte); -- choosing only longest string