Parte 1
Considero que el problema lo tienes aquí:
WHERE categorias.id = subcategorias.id
Puesto que en la condición estás solicitando filas únicamente cuando las llaves primarias en ambas tablas empaten, sin embargo:
- Si existen menos categorías que subcategorías entonces las subcategorías sobrantes es decir que su PK no tengan su correspondiente valor no serán parte de la salida
Parte 2
Considera revisar lo siguiente:
Si hablamos de que una categoría tiene muchas subcategorías entonces la consulta puede quedar de esta forma:
SELECT categorias.*, subcategorias.*
FROM categorias
INNER JOIN subcategorias ON categorias.id = subcategorias.categoria_id;
Usamos la sintaxis regular de joins y en la condición indicamos que las filas devueltas serán siempre y cuando la llave primaria de las categorías sea igual a la llave foránea almacenada por cada fila de las subcategorías.
Es decir algo (muy reducido) de esta forma:
categorias subcategorias
id id
...... ..........
...... ..........
categoria_id <----- esta sería la llave foránea
Donde tendré la salida esperada que es:
- Todas las categorías que tengan al menos una subcategoría asociada por medio de su correspondencia entre llave primaria y llave foránea.
Edición
Quedando así la consulta:
SELECT categorias.nombre, GROUP_CONCAT(subcategorias.nombre)
FROM categorias
INNER JOIN subcategorias ON categorias.id = subcategorias.categoria_id
GROUP BY categorias.nombre;