(SELECT s.name FROM substances s, relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='yellow')
INTERSECT
(SELECT s.name FROM substances s, relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='wood')
Или
SELECT s.name FROM substances s
WHERE exists(SELECT * from relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='yellow')
AND exists(SELECT * from relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='wood')
Наличие единой таблицы options
с property_id
для разделения различных типов опций - не очень хорошая идея, и на самом деле все намного сложнее. Я бы предложил разбить различные виды опций на разные таблицы
MATERIALS(id,name)
COLORS(id,name)
и использование отдельных отношений для каждого типа таблицы. В этом случае вам не понадобятся отдельные таблицы для каждого отношения, так как кажется, что это отношение много (вещество) к одному (цвет).
SUBSTANCES(id, name, material_id, color_id)
Тогда ваш запрос намного проще
SELECT s.name FROM substances s, materials m, colors c
WHERE s.color_id = c.id AND m.material_id = m.id
AND m.name = 'wood'
AND c.name = 'yellow'
ActiveRecord должен легко обрабатывать последний запрос гораздо проще, чем первые два.