Mysql
 sql >> Base de données >  >> RDS >> Mysql

Permutation MySQL

Tous les extras peuvent être dans le bundle ou non, ce qui en fait une propriété binaire.
Une façon de visualiser la combinaison est de créer un mot avec un bit pour chaque extra, 1 signifie que l'extra est dans la liste, 0 signifie que ce n'est pas le cas.
Par exemple Bench + undershelf + overshelf vaut 110 (ou 011 si la chaîne binaire est lue dans l'ordre inverse)

Générer chaque combinaison de n bits donnera chaque combinaison de n extras, cela donnera également chaque nombre à partir de 0 à 2^n - 1 .

Nous pouvons retravailler à partir d'ici :
1. générer la liste des nombres à partir de 0 à 2^n - 1;
2. convertir le nombre en binaire, pour lister la combinaison d'extras
3. assortissez chaque bit avec un extra
4. concaténer les noms des extras dans la description du bundle.

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

cette requête fonctionnera jusqu'à six extras, puis elle aura besoin d'une autre table de chiffres (un chiffre tous les trois extras).

Comment ça marche

La sous-requête E compter le nombre d'extras, ceci est utilisé en C limiter les éléments générés par les tables de chiffres u et t (unité et dizaines) à 2^dim.

Le nombre est converti en binaire par BIN(u.N + t.N * 10) , puis rempli à gauche avec '0' au nombre d'éléments, générant une combinaison bitmap.

Pour utiliser le bitmap généré, chaque extra a besoin d'un faux identifiant qui correspondra à une position dedans, c'est ce que la sous-requête X est destiné.

Les deux sous-requêtes sont JOIN ed par le nième caractère du bitmap :si le caractère est 1, le supplément est dans le bundle, LEFT joints pour ne pas perdre le produit sans extras.