@Tim you have come to the right place.
It just so happens that I answered a question like this ( Find highest level of a hierarchical field: with vs without CTEs ) back in Oct 24, 2011.
I wrote Stored Procedures that traverse a table with id and parent fields. I also included sample data.
However, you may not have to resort to the Stored Procedures.
Here is what I mean: Let's start with the sample data
USE junk
DROP TABLE IF EXISTS pctable;
CREATE TABLE pctable
(
id INT NOT NULL AUTO_INCREMENT,
parent_id INT,
PRIMARY KEY (id)
) ENGINE=MyISAM;
INSERT INTO pctable (parent_id) VALUES (0);
INSERT INTO pctable (parent_id) SELECT parent_id+1 FROM pctable;
INSERT INTO pctable (parent_id) SELECT parent_id+2 FROM pctable;
INSERT INTO pctable (parent_id) SELECT parent_id+3 FROM pctable;
INSERT INTO pctable (parent_id) SELECT parent_id+4 FROM pctable;
INSERT INTO pctable (parent_id) SELECT parent_id+5 FROM pctable;
SELECT * FROM pctable;
To reach any grandparent, you could just perform a JOIN of the pctable against itself:
SELECT P.id,GP.parent_id FROM pctable P
INNER JOIN pctable GP ON P.parent_id = GP.id;
To reach any great-grandparent, you could just perform a JOIN of the pctable against itself twice:
SELECT P.id,GGP.parent_id FROM pctable P
INNER JOIN pctable GP ON P.parent_id = GP.id;
INNER JOIN pctable GGP ON GP.parent_id = GGP.id;
Since your depth is no more than three, doing these JOINs should be quite enough.