按非标量值分组

时间:2014-02-21 17:21:55

标签: sql

鉴于PersonItem

之间的一对多关系
 Person           Item
 -------          ------
 Id   <-----.     Id
 Name       `---- PersonId
                  Label

如果有人和Item.Label可能需要很少的不同值,那么采用等效模式可能是有意义的:

Person        List      Item
--------      ------    ------
Id       .--> Id <--.   Id
ListId --`          `-- ListId
Name                    Label

这样很多人可以共享同一个列表。

从第二个模式到第一个模式的迁移是微不足道的。我的问题是,如何从第一个架构迁移到第二个

挑战在于为

的每个可能结果选择一个代表Person
SELECT Label FROM Item WHERE PersonId = ?

我能够通过使用MS SQL服务器中的FOR XML来解决问题。也就是说,

SELECT P.Id, (SELECT Label FROM Item WHERE PersonId = P.Id FOR XML) list
FROM Person P

然后只需SELECT MIN(P.Id) FROM ... GROUP BY list来收集代表。我对这种解决方法不满意,并希望找到更纯粹的解决方案。

修改

SELECT p.Id, q.Id FROM Person p, Person q
WHERE NOT EXISTS ( --symmetric difference between
    (SELECT Label FROM Item WHERE PersonId = p.Id) --and 
    (SELECT Label FROM Item WHERE PersonId = q.id))

应该是人员的等同关系,需要找到代表。我仍然不知道如何完成,这似乎效率很低。

1 个答案:

答案 0 :(得分:0)

这取决于!我建议你把你的模型贴在你的业务逻辑上。 如果人们拥有预先制作的物品集,那么他就会创造一个表来保持这种逻辑。

考虑人们可以拥有“家庭版”,“专业版”或“标准版”。 在Edition_Items之间创建关系表是有意义的,因为该版本可以包含项目(A,B),(A,B,C,D)和(A,C)等。

你可以在它拥有的People和Edition之间创建一个关系表。在您的场景中,如果版本是“自定义”版本,即使您有两个包含相同的项目集,您可以认为它们是不同的集合(仅仅因为它们由不同的人拥有)。

因此,“Assembled Set”表可用作人与物品之间的关系表。

修改:

OP评论强制执行我的上一次陈述。 因此,您的“列表”表可以是人物和物品之间的关系表。

|People |  |List| |List_Item|  |Item|
|-------|  |----| |---------|  |----|
|P1, L1 |  | L1 | | L1, I1  |  |I1  |
|P2, L2 |  | L2 | | L1, I2  |  |I2  |
           | L3 | | L2, I1  |  |I3  |
           | L4 | | L2, I1  |

看到它你可以问,为什么要保留List表?如果List有一些属性,那就是使用full:isDeleted,Description,CreateTime等

最后一个问题是什么?我们在列表中列出人员列表或人员参考(或创建另一个关系表?)

它依赖于: 1)人员名单是1-1关系? 2)谁先来? (鸡蛋和鸡肉问题?) 这通常是更好的质疑:谁能在没有另一个的情况下存在。