Aqui está o que cada parte da sua consulta faz:
Seleciona colunas específicas:
SELECT p.categoria, c.pais, COUNT(*) AS total_produtos
Exibe a categoria do produto e o pais da categoria, juntamente com o total_produtos, que é o número de produtos em cada grupo (calculado com COUNT(*)).
Define as tabelas e a condição de junção:
FROM produtos p
JOIN categorias c ON p.id_categoria = c.id
Faz uma junção entre as tabelas produtos (alias p) e categorias (alias c) para associar cada produto à sua respectiva categoria.
Aplica um filtro:
WHERE p.preco > 100
Filtra os produtos para considerar apenas aqueles cujo preço é maior que 100.
Agrupa os dados:
GROUP BY p.categoria, c.pais
Agrupa os resultados por p.categoria e c.pais. Ou seja, para cada combinação única de categoria e país, será criado um grupo.
O COUNT(*) então conta quantos produtos existem em cada um desses grupos.
Filtra os grupos com HAVING:
HAVING COUNT(*) > 5
Filtra os grupos para manter apenas aqueles em que o número total de produtos (COUNT(*)) seja maior que 5. O HAVING funciona de forma parecida com o WHERE, mas é usado com agregações, pois ele atua sobre o resultado do GROUP BY.
Ordena os resultados:
ORDER BY total_produtos DESC;
Ordena os resultados em ordem decrescente com base no número de produtos (total_produtos) em cada grupo.
Resumo do que o GROUP BY faz no seu código
Neste código, o GROUP BY p.categoria, c.pais está formando grupos únicos para cada combinação de categoria e pais. Dentro desses grupos, a função COUNT() conta quantos produtos pertencem a cada categoria e país, e o HAVING COUNT() > 5 limita a saída aos grupos com mais de 5 produtos.