Se quelli senza genitori avevano null
nel loro parent
colonna, la tua affermazione sarebbe molto semplice:
SELECT id, name, parent FROM categories order by coalesce(parent, id), id;
Se insisti su 0
non rappresentando alcun genitore, puoi usare CASE WHEN ... THEN ...
in modo più dettagliato dichiarazione.
Modifica:
-- Sorting by name instead
select a.id, a.name, a.parent
from categories a left join categories b on a.parent=b.id
order by coalesce(b.name, a.name), a.name