Esto debería hacerlo. No funcionará en mysql 5.7 porque los CTE recursivos no se incluyeron hasta más tarde, pero esto le permitirá tener una cantidad variable de atributos y valores_de_atributo por ID_de_grupo. El violín está aquí .
with recursive allAtts as (
/* Get our attribute list, and format it if we want; concat(a.title, ':', v.title) looks quite nice */
SELECT
att.group_id,
att.id,
CONCAT(v.title) as attDesc,
dense_rank() over (partition by att.group_id order by att.id) as attRank
FROM table_attributes att
INNER JOIN table_attribute_values v
ON v.group_id = att.group_id
AND v.attribute_id = att.id
),
cte as (
/* Recursively build our attribute list, assuming ranks are sequential and we properly linked our group_ids */
select group_id, id, attDesc, attRank from allAtts WHERE attRank = 1
union all
select
allAtts.group_id,
allAtts.id,
concat_ws('-', cte.attDesc, allAtts.attDesc) as attDesc,
allAtts.attRank
from cte
join allAtts ON allAtts.attRank = cte.attRank +1
AND cte.group_id = allAtts.group_id
)
/* Our actual select statement, which RIGHT JOINs against the table_groups
so we don't lose entries w/o attributes */
select
grp.id,
concat_ws('-', d.day, qty.quantity, cte.attDesc) as combinations
from cte
inner join (select group_id, max(attRank) as attID
from cte
group by group_id) m on cte.group_id = m.group_id and m.attID = cte.attrank
RIGHT JOIN table_groups grp ON grp.id = cte.group_id
LEFT JOIN table_days d on grp.id = d.group_id
LEFT JOIN table_quantities qty on grp.id = qty.group_id;