【发布时间】:2015-11-30 18:06:18
【问题描述】:
我需要根据用户动态添加的属性(转置表)查询用户
我有 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 子句匹配的 where 子句,如下所示: (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 部分 - 析取),如下所示(查询上述 sql fiddle):
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 or 2) 和 (5 or 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 中有解决方案,那也很棒。但如果不是 - 我会翻译它...... 谢谢
【问题讨论】:
-
你有所有这些漂亮的数据作为例子,然后你得到你的问题,你没有显示预期的结果......请包括那个
-
感谢hogen - 将在几秒钟内完成
-
@Hogan - 添加示例
-
例子很糟糕——幸运的是我明白你的意思
-
@Hogan 我只需要用户
标签: sql sql-server jpa where-clause conjunctive-normal-form