SELECT `item_id`
FROM `table`
WHERE (property_id = 2 AND value_id = 3)
OR (property_id = 2 AND value_id = 5)
OR (property_id = 1 AND value_id = 4)
GROUP BY `item_id`
HAVING COUNT(`item_id`) = 3
WITH RECURSIVE linked(id, path) AS (
SELECT :id,
ARRAY[:id]
UNION ALL
SELECT t3b.table1_id,
path || t3b.table1_id
FROM table3 AS t3a, table3 AS t3b, linked AS l
WHERE t3a.table1_id = l.id
AND t3b.table2_id = t3a.table2_id
AND t3b.table1_id != t3a.table1_id
AND NOT (t3b.table1_id = ANY(path))
)
SELECT * FROM linked;