Вариант 1. Работает, если в `goods_property` каждая комбинация (`goods_id`, `type`, `value`) встречается не более одного раза.
SELECT `g`.*
FROM (
SELECT `goods_id`
FROM `goods_property`
WHERE (`type` = 'caffeine_capacity' AND `value` = 'small')
OR (`type` = 'color_type' AND `value` = 'green')
GROUP BY `goods_id`
HAVING COUNT(*) = 2
) AS `p`
JOIN `goods` AS `g` ON `g`.`id` = `p`.`goods_id`
Вариант 2. Если таблица кривая и комбинация может встретиться более одного раза, то
SELECT `g`.*
FROM `goods` AS `g`
JOIN `goods_property` AS `p1` ON `p1`.`goods_id` = `g`.`id`
AND `p1`.`type` = 'caffeine_capacity' AND `p1`.`value` = 'small'
JOIN `goods_property` AS `p2` ON `p2`.`goods_id` = `g`.`id`
AND `p2`.`type` = 'color_type' AND `p2`.`value` = 'green'
Вариант 3. Тоже для кривой таблицы.
SELECT `g`.*
FROM `goods`
WHERE `id` IN (
SELECT `goods_id`
FROM `goods_property`
WHERE `type` = 'caffeine_capacity' AND `value` = 'small'
) AND `id` IN (
SELECT `goods_id`
FROM `goods_property`
WHERE `type` = 'color_type' AND `value` = 'green'
)
В качестве песочницы попробуйте
https://www.db-fiddle.com/