Tendrá que usar el procedimiento almacenado para hacerlo.
Encuentre todas las filas con capacidad de búsqueda =1, almacene sus ID y parent_ids en una tabla temporal. Luego haga auto-uniones para agregar padres a esta tabla temporal. Repita hasta que no se puedan agregar más filas (obviamente, es mejor asegurarse de que el árbol no sea cíclico). Al final, tiene una tabla solo con filas que tienen un descendiente que se puede buscar en algún lugar del árbol, así que solo muestre filas sin padre (en la parte superior).
Suponiendo que su tabla se llame 'my_table', esta debería funcionar:
DELIMITER //
DROP PROCEDURE IF EXISTS top_level_parents//
CREATE PROCEDURE top_level_parents()
BEGIN
DECLARE found INT(11) DEFAULT 1;
DROP TABLE IF EXISTS parent_tree;
CREATE TABLE parent_tree (id int(11) PRIMARY KEY, p_id int(11)) ENGINE=HEAP;
INSERT INTO parent_tree
SELECT id, parent_id FROM my_table
WHERE searchable = 1;
SET found = ROW_COUNT();
WHILE found > 0 DO
INSERT IGNORE INTO parent_tree
SELECT p.id, p.parent_id FROM parent_tree c JOIN my_table p
WHERE p.id = c.p_id;
SET found = ROW_COUNT();
END WHILE;
SELECT id FROM parent_tree WHERE p_id = 0;
DROP TABLE parent_tree;
END;//
DELIMITER ;
Entonces simplemente llamándolo:
CALL top_level_parents();
será igual a SELECT id FROM my_table WHERE id_is_top_level_and_has_searchable_descendant