CASE with parent and child existence checks
SELECT
id,
CASE
WHEN p_id IS NULL THEN 'Root'
WHEN id IN (SELECT p_id FROM tree WHERE p_id IS NOT NULL) THEN 'Inner'
ELSE 'Leaf'
END AS type
FROM treeThe logic mirrors the node definitions directly. A root has no parent, an inner node appears as someone else’s parent, and everything left over is a leaf.