Todos los extras pueden estar en el paquete o no, lo que lo convierte en una propiedad binaria.
Una forma de visualizar la combinación es crear una palabra con un bit para cada extra, 1
significa que el extra está en la lista, 0
significa que no lo es.
Por ejemplo Bench + undershelf + overshelf
es 110 (o 011 si la cadena binaria se lee en el orden opuesto)
Generar cada combinación de n bits dará cada combinación de n extras, también dará cada número desde 0
a 2^n - 1
.
Podemos trabajar desde aquí:
1. generar la lista de números desde 0
a 2^n - 1
;
2. convertir el número a binario, para listar la combinación de extras
3. combina cada bit con un extra
4. concatene los nombres de los extras en la descripción del paquete.
SELECT CONCAT(b.Name
, COALESCE(CONCAT(' + '
, GROUP_CONCAT(x.Name SEPARATOR ' + '))
, '')) Combination
FROM (SELECT p.Name, p.id
, LPAD(BIN(u.N + t.N * 10), e.Dim, '0') bitmap
FROM Products p
CROSS JOIN (SELECT 0 N UNION ALL SELECT 1
UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9) u
CROSS JOIN (SELECT 0 N UNION ALL SELECT 1
UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9) t
INNER JOIN (SELECT COUNT(1) Dim
, `Parent ID` pID
FROM Extra) E ON e.pID = p.ID
WHERE u.N + t.N * 10 < Pow(2, e.Dim)
) B
LEFT JOIN (SELECT @rownum := @rownum + 1 ID
, `Parent ID` pID
, Name
FROM Extra
, (Select @rownum := 0) r) X
ON x.pID = b.ID
AND SUBSTRING(b.bitmap, x.ID, 1) = '1'
GROUP BY b.Name, b.bitmap
esta consulta funcionará hasta con seis extras, luego necesitará otra tabla de dígitos (un dígito cada tres extras).
Cómo funciona
La subconsulta E
cuente el número de extras, esto se usa en C
para limitar los elementos generados por las tablas de dígitos u
y t
(unidad y decenas) a 2^dim.
El número se convierte a binario por BIN(u.N + t.N * 10)
, luego se rellena con '0' a la izquierda para el número de elementos, generando un mapa de bits de combinación.
Para usar el mapa de bits generado, cada extra necesita una identificación falsa que coincida con una posición en él, eso es lo que la subconsulta X
está destinado a.
Las dos subconsultas son JOIN
ed por el carácter n del mapa de bits:si el carácter es 1, el extra está en el paquete, LEFT
unidos para no perder el producto sin extras.