About 15 years ago I wrote a function to produce this
from data very much like yours EG
SELECT * FROM horse;
+----+------+------+------+----------+
| id | name | sire | dam | gender |
+----+------+------+------+----------+
| 26 | A | 27 | 39 | STALLION |
| 27 | B | 28 | 40 | STALLION |
| 28 | C | 29 | 40 | STALLION |
| 29 | D | 30 | 40 | STALLION |
| 30 | E | 31 | 41 | STALLION |
| 31 | F | 32 | 41 | STALLION |
| 32 | G | 33 | 42 | STALLION |
| 33 | H | 33 | 42 | STALLION |
| 34 | I | 35 | 43 | STALLION |
| 35 | J | 36 | 43 | STALLION |
| 36 | K | 37 | 44 | STALLION |
| 37 | L | 38 | 44 | STALLION |
| 38 | M | 34 | 45 | STALLION |
| 39 | N | 29 | 46 | MARE |
| 40 | O | 27 | 51 | MARE |
| 41 | P | 28 | 51 | MARE |
| 42 | Q | 29 | 50 | MARE |
| 43 | R | 30 | 50 | MARE |
| 44 | S | 31 | 49 | MARE |
| 45 | T | 32 | 49 | MARE |
| 46 | U | 33 | 48 | MARE |
| 47 | V | 34 | 48 | MARE |
| 48 | W | 35 | 46 | MARE |
| 49 | X | 36 | 46 | MARE |
| 50 | Y | 37 | 47 | MARE |
| 51 | Z | 38 | 47 | MARE |
+----+------+------+------+----------+
It uses a recursive* function which gets the sire and dam for the horse $id and outputs the name. It then calls itself for the sire and the dam which outputs their names and get their parents. This is repeated until the specified level of ancestry is reached.
Is that the sort of thing you are trying to do?
If so, give it a go using the method I described and come back if oyu get stuck
* recursion : see recursion