動的に追加されたプロパティ (転置テーブル) に従ってユーザーにクエリを実行する必要があります
私は4つのテーブルを持っています
- ユーザー- ユーザー向け
- propertyGroup - プロパティのグループの場合、グループをデータベースに動的に追加できます
- propertyValue - propertyGroup の可能な値
- usersPropertyValues - ユーザーを関連するプロパティに接続します
その外観は次のようになります。
users:
------
| id | name | details |
|----|------|---------|
| 1 | Joe | foo |
| 2 | Dan | bar |
propertyGroup:
--------------
| id | name |
|----|----------------|
| 1 | Hobbies |
| 2 | LikeFood |
| 3 | VisitedCountry |
propertyValue:
--------------
| id | propertyGroupId | name |
|----|-----------------|--------------|
| 1 | 1 | Technologies |
| 2 | 1 | Surfing |
| 3 | 2 | Rice |
| 4 | 2 | Meat |
| 5 | 2 | Veg |
| 6 | 3 | USA |
| 7 | 3 | FRANCE |
| 8 | 3 | ISRAEL |
| 9 | 3 | CANADA |
usersPropertyValues:
--------------------
| userId | propertyValueId |
|--------|-----------------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 5 |
| 1 | 6 |
| 1 | 7 |
| 1 | 8 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 2 | 5 |
| 2 | 8 |
| 2 | 9 |
| 2 | 7 |
したがって、mix-em-all クエリは次のようになります。
select *
from users as u
join usersPropertyValues as upv on upv.userId = u.id
join propertyValues as pv on pv.id = upv.propertyValueId
join propertyGroup as pg on pg.id = pv.propertyGroupId
| id | name | details | userId | propertyValueId | id | propertyGroupId | name | id | name |
|----|------|---------|--------|-----------------|----|-----------------|--------------|----|----------------|
| 1 | Joe | foo | 1 | 1 | 1 | 1 | Technologies | 1 | Hobbies |
| 1 | Joe | foo | 1 | 2 | 2 | 1 | Surfing | 1 | Hobbies |
| 1 | Joe | foo | 1 | 3 | 3 | 2 | Rice | 2 | LikeFood |
| 1 | Joe | foo | 1 | 5 | 5 | 2 | Veg | 2 | LikeFood |
| 1 | Joe | foo | 1 | 6 | 6 | 3 | USA | 3 | VisitedCountry |
| 1 | Joe | foo | 1 | 7 | 7 | 3 | FRANCE | 3 | VisitedCountry |
| 1 | Joe | foo | 1 | 8 | 8 | 3 | ISRAEL | 3 | VisitedCountry |
| 2 | Dan | bar | 2 | 2 | 2 | 1 | Surfing | 1 | Hobbies |
| 2 | Dan | bar | 2 | 3 | 3 | 2 | Rice | 2 | LikeFood |
| 2 | Dan | bar | 2 | 4 | 4 | 2 | Meat | 2 | LikeFood |
| 2 | Dan | bar | 2 | 5 | 5 | 2 | Veg | 2 | LikeFood |
| 2 | Dan | bar | 2 | 8 | 8 | 3 | ISRAEL | 3 | VisitedCountry |
| 2 | Dan | bar | 2 | 9 | 9 | 3 | CANADA | 3 | VisitedCountry |
| 2 | Dan | bar | 2 | 7 | 7 | 3 | FRANCE | 3 | VisitedCountry |
そのすべてがここにあります:http://sqlfiddle.com/#!3/49329/1
propertyValueIdのセットでデータをクエリし、グループに関してこのプロパティのセットに一致するすべてのユーザーを取得したいので、ユーザーはすべてのグループから少なくともプロパティを持っている必要があります。次のような一般的な CNF 句に一致します: (pvId は propertyValueId の省略形です)
Property group A Property group B Property group C
(pvId_x or pvId_y) and (pvId_w or pvId_z) and... and (pvId_m or pvId_k)
上記の例では、pvId_x&pvId_y はグループ A に属し、pvId_w&pvId_z はグループ B に属します。
私がうまくいかなかったのは、ここに示されているように、IN演算子のAND演算子を連結しようとしました( or 一部をシミュレートします - 論理和):
select distinct u.name, u.id
from users as u
join usersPropertyValues as upv on upv.userId = u.id
join propertyValues as pv on pv.id = upv.propertyValueId
join propertyGroup as pg on pg.id = pv.propertyGroupId
where (pv.propertyGroupId = 1 AND pv.id IN(1,2)) and (pv.propertyGroupId = 2 AND pv.id IN(5,6))
両方のユーザーを取得する代わりに (両方とも (1 または 2) と (5 または 6) を持っています)、何も取得しませんでした。
結果セットが空である理由は理解していますが、適切な where 句を実装する方法は理解していません。- どのようにそれを行うことができますか?
私の質問: 上記の SQL 構造に CNF ロジックを実装するにはどうすればよいですか?
編集:除外された結果の例: (sqlfiddle の例に関して:
input --> output
{1,5} --> Joe (user with hobby:tech, likefood:veg)
{2,8} --> Joe,Dan (user with hobby:surfing, VisitedCountry:Israel)
{2,8,9} --> Dan (user with hobby:surfing, VisitedCountry:Israel,Canada)
ところで、これを最後に JPA に実装する必要があるため、JPA に解決策があればそれも素晴らしいことです。そうでない場合は、翻訳します...ありがとう