Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Permutação do MySQL


Todos os extras podem estar no pacote ou não, tornando isso uma propriedade binária.
Uma maneira de visualizar a combinação é criar uma palavra com um bit para cada extra, 1 significa que o extra está na lista, 0 significa que não é.
Por exemplo Bench + undershelf + overshelf é 110 (ou 011 se a string binária for lida na ordem oposta)

Gerar todas as combinações de n bits fornecerá todas as combinações de n extras, também fornecerá todos os números de 0 para 2^n - 1 .

Podemos trabalhar a partir daqui:
1. gerar a lista de números de 0 para 2^n - 1;
2. converter o número para binário, para listar a combinação de extras
3. combine cada bit com um extra
4. concatenar os nomes dos extras na descrição do pacote.
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á até seis extras, então precisará de outra tabela de dígitos (um dígito a cada três extras).

Como funciona

A subconsulta E conte o número de extras, isso é usado em C para limitar os elementos gerados pelas tabelas de dígitos u e t (unidade e dezenas) para 2^dim.

O número é convertido em binário por BIN(u.N + t.N * 10) , em seguida, preenchido à esquerda com '0' para o número de elementos, gerando um bitmap de combinação.

Para usar o bitmap gerado, cada extra precisa de um id falso que corresponda a uma posição nele, é o que a subconsulta X é destinado.

As duas subconsultas são JOIN ed pelo enésimo caractere do bitmap:se o caractere for 1, o extra está no pacote, LEFT unidos para não soltar o produto sem extras.