在JOIN中进行的多对多关系研究

时间:2010-07-04 09:10:29

标签: sql tsql database-design

如果愿意,请考虑以下表格:

Vacation Model http://imagetiger.org/images/vacatilrl.png

这可能看起来像一个奇怪的结构,但请允许我解释一下。这个结构的目标是创建一个列出所有人的报告,不包括那些度假的人(为简单起见,我们假装假期记录只有在一个人休假时才会存在。)

我拥有Vacation表的原因是因为Event表是“无关紧要”事件的更通用表,而Vacation表包含更多详细信息,例如位置和日期。

我似乎无法弄清楚如何设计一个包含Person.personId和Vacation.location的查询,但只包含Person_Vacation中存在的那些personId。或者反之,只有Person_Vacation中不存在的personIds。

此外,这似乎是设计方面实施此解决方案的最佳方式吗?关于我可能做错了什么或建议改进的任何想法?

编辑:也许我只是不太善于传达我的意图:结果只让度假的人很容易,但我想执行反向,基本上所有的人都没有假期。

2 个答案:

答案 0 :(得分:5)

设计明智我不明白为什么你需要Person_Vacation。如果我正确理解您的设计,每个假期都是一个事件(即“继承”),因此VacationPerson之间的联系可以通过Person_Event进行。然后查询将是:

度假的人:

SELECT P.PersonID, V.locaton
FROM Person P, Vacation V, Person_Event PE
WHERE P.personid = PE.personID AND PE.eventid = V.eventid

非假期活动的人:

SELECT P.PersonID, E.title
FROM Person P, Person_Event PE, Event E
WHERE P.personid = PE.personID AND PE.eventid = E.eventid
AND E.eventID NOT IN (SELECT eventid FROM Vacation)

不在任何度假的人:

SELECT P.PersonID, E.title
FROM Person P, Person_Event PE, Event E
WHERE P.personid = PE.personID AND PE.eventid = E.eventid
AND P.personID NOT IN 
  (SELECT personid FROM Person_Event PE, Vacation V WHERE PE.eventid = V.eventid)

如果您想使用自己的设计,那么您必须决定是否仅在Person_VacationPerson_VacationPerson_Event中插入一个人的假期。如果你做前者,那么上面的查询会变得有点简单。

但是我仍然会投票支持我的设计,因为你实际上在做的是过早地分割数据只是为了获得一点性能/简单性。从长远来看,这可能无法获得回报。

答案 1 :(得分:0)

可能我对你的数据库设计并不完全了解。如果Vocation也是一个事件,并且Person_Event表包含所有与该人personId相关的事件,那么该表应该包含Person_Vacation的子集,并且可以消除它。此外,所有人都有一些时间的职业,所以我会发现在一些表格中包含日期更合乎逻辑。

如果我对您的数据库设计不合理,您可以通过以下查询获得所需的结果

SELECT p.name, e.title
FROM Person AS p
    INNER JOIN Person_Event AS pe ON p.personId = pe.personId
    INNER JOIN [Event] AS e ON pe.eventId = e.eventId
    LEFT OUTER JOIN Vacation AS v ON e.eventId = v.eventId
WHERE v.eventId IS NULL
相关问题