Ще трябва да използвате съхранена процедура, за да го направите.
Намерете всички редове с възможност за търсене =1, съхранете техните идентификатори и parent_ids във временна таблица. След това направете самостоятелно присъединяване, за да добавите родители към тази временна таблица. Повторете, докато не могат да се добавят повече редове (очевидно е по-добре да се уверите, че дървото не е циклично). В края имате таблица само с редове, които имат наследник за търсене някъде надолу в дървото, така че просто покажете само редове без родител (в горната част).
Ако приемем, че вашата таблица се нарича 'my_table', тази би трябвало да работи:
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 ;
След това просто го извикате:
CALL top_level_parents();
ще бъде равно наSELECT id FROM my_table WHERE id_is_top_level_and_has_searchable_descendant