sql >> Base de Datos >  >> RDS >> Mysql

permutación MySQL

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.