Всегда лучше поддерживать базу данных в норме. В вашем конкретном случае я бы сохранил количество элементов для каждого соединения вместо новой строки для каждого элемента.
compound_id element_id bond count
-------------------------------------------------
"Water" "H" "Covalent" 2
"Water" "O" "Covalent" 1
Запрос на точное совпадение будет
select compound_id
from elements
group by compound_id
having count(
case when
(element_id = 'H' and count = 2) or
(element_id = 'O' and count = 1) then 1
end
) = count(*)
Однако этот подход будет неоптимальным, поскольку будет использоваться последовательное сканирование. Если денормализация не является проблемой, может помочь хранение нескольких различных элементов для каждого соединения.
compound_id element_count
------------------------------
"Water" 2
Тогда запрос может быть
select e.compound_id
from elements e
join compounds c on e.compound_id = c.compound_id
where c.element_count = 2 and
((e.element_id = 'H' and e.count = 2) or
(e.element_id = 'O' and e.count = 1))
group by e.compound_id
having count(*) = 2
и если у вас есть индекс для compounds(element_count)
и elements(element_id, count)
, тогда ваш запрос будет использовать его для быстрого получения результатов, даже если база данных большая.