I have the following table:
id | parent_id | searchable | value
--------------------------------------------
1 | 0 | 0 | a
Recursive queries can be done in Newer Mysql, possibly not around back when this was asked.
Get parents and children data where top level parent has a name of "A" or "B" or "C".
RECURSIVE MySQL 8.0 compatibility. https://dev.mysql.com/doc/refman/8.0/en/with.html
The first part gets the parent top level and filters it, the second gets the children joining to their parents.
WITH RECURSIVE tree AS (
SELECT id,
name,
parent_id,
1 as level
FROM category
WHERE parent_id = 0 AND (name = 'A' or name = 'B' or name = 'C')
UNION ALL
SELECT c.id,
c.name,
c.parent_id,
t.level + 1
FROM category c
JOIN tree t ON c.parent_id = t.id
)
SELECT *
FROM tree;
To find if the parent or one of its children have searchable, you can pull through that value with a COALESCE(NULLIF(p.searchable,0), NULLIF(c.searchable,0)) and by pulling through the top level parent id and joining back against it.
So to initialize your example data:
CREATE TABLE `category` (
`id` int(11) NOT NULL,
`parent_id` int(11) NULL DEFAULT NULL,
`searchable` int(11) NULL DEFAULT NULL,
`value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO category (id, parent_id, searchable, value) VALUES
(1,0,0,'a'),
(2,1,0,'b'),
(3,2,1,'c'),
(4,0,0,'d'),
(5,4,1,'e'),
(6,0,0,'f'),
(7,6,0,'g'),
(8,6,0,'h'),
(9,0,1,'i');
And to answer the question.
WITH RECURSIVE tree AS (
SELECT id,
value,
parent_id,
1 as level,
searchable,
id AS top_level_id
FROM category
WHERE parent_id = 0
UNION ALL
SELECT c.id,
c.value,
c.parent_id,
t.level + 1,
COALESCE(NULLIF(t.searchable,0), NULLIF(c.searchable,0)),
COALESCE(t.top_level_id) AS top_level_id
FROM category c
JOIN tree t ON c.parent_id = t.id
)
SELECT category.*
FROM category
LEFT JOIN tree ON tree.top_level_id = category.id
WHERE tree.searchable = 1;
Note: Does not handle cyclic linkages. If you have those, you need to remove them or constraint it so it does not happen, or add a visited column in much the same way you can bring through the top level id possibly.