Поэтому я хочу выбрать все строки, где подмножество строк в другой таблице соответствуют заданным значениям.
У меня есть следующие таблицы:
Main Profile:
+----+--------+---------------+---------+
| id | name | subprofile_id | version |
+----+--------+---------------+---------+
| 1 | Main 1 | 4 | 1 |
| 2 | Main 1 | 5 | 2 |
| 3 | Main 2 | ... | 1 |
+----+--------+---------------+---------+
Sub Profile:
+---------------+----------+
| subprofile_id | block_id |
+---------------+----------+
| 4 | 6 |
| 4 | 7 |
| 5 | 8 |
| 5 | 9 |
+---------------+----------+
Block:
+----------+-------------+
| block_id | property_id |
+----------+-------------+
| 7 | 10 |
| 7 | 11 |
| 7 | 12 |
| 7 | 13 |
| 8 | 14 |
| 8 | 15 |
| 8 | 16 |
| 8 | 17 |
| ... | ... |
+----------+-------------+
Property:
+----+--------------------+--------------------------+
| id | name | value |
+----+--------------------+--------------------------+
| 10 | Description | XY |
| 11 | Responsible person | Mr. Smith |
| 12 | ... | ... |
| 13 | ... | ... |
| 14 | Description | XY |
| 15 | Responsible person | Mrs. Brown |
| 16 | ... | ... |
| 17 | ... | ... |
+----+--------------------+--------------------------+
Пользователь может определить несколько условий в таблице свойств. Например:
- Описание = 'XY'
- Ответственный = Мистер Smith '
Мне нужны все «Главные профили» с самой высокой версией, которые имеют ВСЕ подходящие свойства и, конечно, могут иметь больше, которые не совпадают.
Это должно быть выполнимо в JPA, потому что я бы перевел его в QueryDSL для построения безопасных динамических запросов с пользовательским вводом.
Я уже искал все вопросы, касающиеся подобных проблем, но не смог спроецировать ответ на свою проблему.
Кроме того, я уже пытался написать запрос, который работал довольно хорошо, но получил все строки, по крайней мере, с одним условием соответствия. Поэтому мне нужны все свойства в моем наборе, но он только извлекает (выбирает соединение, которого нет в моем примере кода) совпадающие.
from MainProfile as mainProfile
left join mainProfile.subProfile as subProfile
left join subProfile.blocks as block
left join block.properties as property
where mainProfile.version = (select max(mainProfile2.version)from MainProfile as mainProfile2 where mainProfile2.name = mainProfile.name) and ((property.name = 'Description' and property.value = 'XY') or (property.name = 'Responsible person' and property.value = 'Mr. Smith'))
Запустив мой запрос, я получил две строки:
- Main 1 с версией 2
- Main 2 с версией 1
Я бы ожидал получить только один ряд из-за несоответствия «ответственного лица» в «Основном 2»
РЕДАКТИРОВАТЬ 1:
Итак, я нашел решение, которое работает, но может быть улучшено:
select distinct mainProfile
from MainProfile as mainProfile
left join mainProfile.subProfile as subProfile
left join subProfile.blocks as block
left join block.properties as property
where mainProfile.version = (select max(mainProfile2.version)from MainProfile mainProfile2 where mainProfile2.name = mainProfile.name)
and ((property.name = 'Description' and property.content = 'XY') or (property.name = 'Responsible person' and property.content = 'Mr. Smith'))
group by mainProfile.id
having count (distinct property) = 2
На самом деле он получает нужные «Основные профили». Но проблема в том, что извлекаются только два найденных свойства. Мне нужны все свойства из-за дальнейшей обработки.