If you have a potentially large depth (e.g. 1000) that you have to deal with, you can do the calculation in O(log n) steps with some secondary tables. Something like:
create table edge_depth0 as
select parent, child, 1 as depth from edges;
create table edge_depth_join as
select d0.parent, d1.child, d0.depth + d1.depth as depth
from edge_depth0 d0 join edge_depth0 d1
on d0.child = d1.parent;
create table edge_depth1 as
select parent, child, max(depth) as depth
from
(
select parent, child, depth
from edge_depth0
union
select parent, child, depth
from edge_depth_join
)
group by parent, child;
and then ping-ponging between edge_depth0 and edge_depth1 like so:
truncate table edge_depth_join;
insert into edge_depth_join (parent, child, depth)
select d0.parent, d1.child, d0.depth + d1.depth
from edge_depth1 d0 join edge_depth1 d1
on d0.child = d1.parent;
truncate table edge_depth0;
insert into edge_depth0 (parent, child, depth)
select parent, child, max(depth)
from
(
select parent, child, depth
from edge_depth1
union
select parent, child, depth
from edge_depth_join
)
group by parent, child;
truncate table edge_depth_join;
insert into edge_depth_join (parent, child, depth)
select d0.parent, d1.child, d0.depth + d1.depth
from edge_depth0 d0 join edge_depth0 d1
on d0.child = d1.parent;
truncate table edge_depth1;
insert into edge_depth1 (parent, child, depth)
select parent, child, max(depth)
from
(
select parent, child, depth
from edge_depth0
union
select parent, child, depth
from edge_depth_join
)
group by parent, child;
Once you find that the number of rows in edge_depth0 is equal to the number of rows in edge_depth1, you can stop ping-ponging. Then, to get the depth of every node you then do the query:
create table node_depth as
select child as node, max(depth) as depth
from edge_depth1
group by child
union
select e0.parent as node, 0 as depth
from edges e0 left join edges e1
on e0.parent = e1.child
where e1.child is null;
Note that the second part of the union is to get the root of the tree or trees in the data structure, which themselves might be leaves if they have no children. Finally, if all you want are just the depths of the leaves in the data – say, sorted by node – you do:
select n.*
from node_depth left join edges e
on n.node = e.parent
where e.parent is null
order by node;
Note that while the number of steps is O(log n), the data size is O(n[sup]2[/sup]).