Esta consulta retorna todos os itens associados às categorias em ordem aleatória:
SELECT
c.id AS cid, c.category, i.id AS iid, i.name
FROM categories c
INNER JOIN items i ON c.id = i.category
ORDER BY RAND()
Para restringir cada categoria a uma, envolva a consulta em um parcial
GROUP BY
:SELECT * FROM (
SELECT
c.id AS cid, c.category, i.id AS iid, i.name
FROM categories c
INNER JOIN items i ON c.id = i.category
ORDER BY RAND()
) AS shuffled_items
GROUP BY cid
Observe que quando uma consulta tem
GROUP BY
e ORDER BY
cláusula, o agrupamento é executado antes da classificação. É por isso que usei duas consultas:a primeira classifica os resultados, a segunda agrupa os resultados. Eu entendo que esta consulta não vai ganhar nenhuma corrida. Estou aberto a sugestões.