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.