2010-10-20 41 views
5

这是一个棘手的规范化/ SQL /数据库设计问题,令我们感到困惑。我希望我能正确地说出来。设计这个特定数据库/ SQL问题的最佳方法是什么?

您有一组活动。他们是需要完成的事情 - 一个荣耀的TODO清单。任何给定的活动都可以分配给员工。

每个活动都有一个活动的执行者。这些活动是联系人(人)或客户(业务)。每个活动都会有一个联系人或一个客户,他们将完成活动。例如,该活动可能是“向Spacely Sprockets(客户)发送感谢卡”或“向Tony Almeida(联系人)发送营销文献”。

从这个结构,我们就需要能够查询找到所有指定员工必须做的活动,在一个单一的关系,列出他们会是这样的在它最简单的形式:

----------------------------------------------------- 
| Activity | Description | Recipient of Activity | 
----------------------------------------------------- 

这里的想法是避免让联系人和客户有两列为空。

我希望我已经正确描述了这一点,因为这并不像第一眼那样明显。

所以问题是:什么是数据库的“正确”的设计,你将如何查询它来获取所需的信息?

+0

似乎有关于客户和联系人的一些混淆。他们分开桌子吗?客户和联系人之间是否有任何关系?他们是否需要使用现有的表格,还是新的或可重构的表格? – ulty4life 2010-10-21 02:55:12

+0

是的,客户和联系人是独立的实体。也许他们不应该,但他们是。 ;-) – 2010-10-21 17:23:39

回答

2

这是我在它刺伤:

基本上你需要活动相关联,以1(接触或客户)和1名员工是做一个负责任的人的活动。请注意,您可以在像这样的模型中处理参照约束。

另外请注意我说的是连接所有人民和地方的businessEntity表。 (有时有用但不是必需的)。之所以把businessEntity的表你可以简单的参考的,应当负责和对活动的businessEntity的收件人,现在你可以有活动的任何和所有的人或地方预制和接收。

alt text

1

你必须像如下:

Activity | Description | Recipient Type

Recipient TypeContact一个或Customer

你会再执行一个SQL SELECT语句如下:
Select * from table where Recipient_Type = 'Contact';

我意识到需要有更多的信息。

我们需要一个额外的表,它是代表接收者(联系人和客户)的:

此表应如下所示:

ID | Name| Recipient Type

Recipient Type将表中的一个关键参考最初在这篇文章中提到过。当然,需要完成工作来处理这些表中的级联,主要是更新和删除。因此,快速回顾一下:

Recipients.Recipient_Type是一个FK到Table.Recipient_Type

+1

它说这个模型中的收件人是谁?你将如何管理“联系人”/“客户”的外键?你会区分这些吗? – 2010-10-20 21:07:15

+0

不太清楚我关注你的问题马丁,我现在看到 – Woot4Moo 2010-10-20 21:09:01

+1

这应该更流畅,回答这个问题。让我知道是否需要更多解释 – Woot4Moo 2010-10-20 21:09:54

4

“正确”的设计,这个数据库是有一列的每个,你说你要设法避免。这允许在这两列和它们各自的表之间定义适当的外键关系。对引用两个不同表的键使用同一列会使查询变得丑陋,并且不能强制引用完整性。

活动表应该有外键的ContactID,客户ID

为了显示活动的员工:

SELECT ActivityName, ActivityDescription, CASE WHEN a.ContactID IS NOT NULL THEN cn.ContactName ELSE cu.CustomerName END AS Recipient 
FROM activity a 
LEFT JOIN contacts cn ON a.ContactID=cn.ContactID 
LEFT JOIN customers cu ON a.CustomerID=cu.CustomerID 
+0

我认为在您的关系数据库中存在外键的根本误解。 – Woot4Moo 2010-10-20 21:14:24

+0

不确定你的意思。我可能已经对OP的建议做了一个假设。 – 2010-10-20 21:18:51

+0

我注意到的问题与具有良好图表的帖子中的问题相同。随着更多类型的收件人的添加,这将如何成为未来的维护问题。最合适的方式,请参阅可维护的方法,即有一个Recipients表,允许添加/修改Recipient_Type列,但不会对维护数据库的任何人的灵魂造成严重损害。 – Woot4Moo 2010-10-20 21:23:54

9

这听起来像一个基本的许多一对多的关系,我想它的模型本身。

alt text

+0

这个比例因为在维护方面增加了更多类型的收件人? – Woot4Moo 2010-10-20 21:19:24

+0

我喜欢这种方式,但是它增加了两个额外的表格和额外的功能,除非需要为单个活动设置多个“收件人”认为在Activity表上有两个外键会更简单 – 2010-10-20 21:28:12

+0

@ Woot4Moo:显然它通过需要额外的表来扩展,但它避免了sol中提到的级联问题ution。 – 2010-10-20 21:31:16

0
[ActivityRecipientRecipientType] 
    ActivityId 
    RecipientId 
    RecipientTypeCode 
     ||| ||| |||_____________________________  
     |  |         | 
     |  --------------------    | 
     |      |    | 
    [Activity]    [Recipient]  [RecipientType] 
    ActivityId    RecipientId  RecipientTypeCode 
    ActivityDescription  RecipientName RecipeintTypeName 


    select 
     [Activity].ActivityDescription 
    , [Recipient].RecipientName 
    from 
     [Activity] 
    join [ActivityRecipientRecipientType] on [Activity].ActivityId = [ActivityRecipientRecipientType].ActivityId 
    join [Recipient] on [ActivityRecipientRecipientType].RecipientId = [Recipient].RecipientId 
    join [RecipientType] on [ActivityRecipientRecipientType].RecipientTypeCode = [RecipientType].RecipientTypeCode 
    where [RecipientType].RecipientTypeName = 'Contact' 
+0

小心解释多个连接的需求以及这不会成为DBA的噩梦吗? – Woot4Moo 2010-10-20 21:20:51

4

它为什么要定义客户和联系人作为独立的实体,当他们似乎是同一实体的版本是我不明白。在我看来,客户是联系人的附加信息。如果可能的话,我会建立联系的一个表,然后标记是客户的那些要么在该表中的字段,或通过添加自己的ID来已在它的扩展单客户信息表客户。

如果你不能做到这一点(因为这是被建立在现有的系统,其设计是固定的顶部),那么你有几种选择。没有一个选择是好的,因为它们无法真正解决原始缺陷,即单独存储客户和联系人。

  1. 使用两列,一个NULL,以允许参照完整性工作。

  2. 建设有其自身的PK和两列,一个NULL,中间表ActivityContacts指向客户或联系人。这可以让你建立一个“干净的”活动系统,但是会把丑陋推向那个中间表。 (它确实提供了一个可能的好处,那就是它允许您将活动的目标限制到添加到中间表的人员,如果这对您有利的话)。

  3. 携带原设计缺陷到活动系统和(我在这里咬我的舌头)具有平行ContactActivity和CustomerActivity表。要查找员工分配的所有任务,请将这两个表一起放入一个VIEW中。这使您可以保持参照完整性,不需要NULL列,并为您提供从中获取报告的来源。

0
Actions 
Activity_ID | Description | Recipient ID 
------------------------------------- 
11 | Don't ask questions | 0 
12 | Be cool | 1 

Activities 
ID | Description 
---------------- 
11 | Shoot 
12 | Ask out 

People 
ID | Type | email | phone | GPS |.... 
------------------------------------- 
0 | Troll | [email protected] | 232323 | null | ... 
1 | hottie | [email protected] | 2341241 | null | ... 


select at.description,a.description, p.* from Activities at, Actions a, People p 
where a."Recipient ID" = p.ID 
    and at.ID=a.activity_id 

result: 

Shoot | Don't ask questions | 0 | Troll | [email protected] | 232323 | null | ... 
Ask out | Be cool | 1 | hottie | [email protected] | 2341241 |null | ... 
1

alt text

2

如果我读过的情况下正确的,收件人是客户和联系人的推广。
Gen-spec设计模式很好理解。

Data modeling question

0

模型的另一个实体:ActivityRecipient,将由ActivityRecipientContact和ActivityRecipientCustomer继承,这将保持适当的客户/联系人ID。

相应的表格将是:

Table: Activities(...., RecipientID) 

Table: ActivityRecipients(RecipientID, RecipientType) 

Table: ActivityRecipientContacts(RecipientID, ContactId, ...,ExtraContactInfo...) 

Table: ActivityRecipientCustomers(RecipentID, CustomerId, ...,ExtraCustomerInfo...) 

这种方式,你也可以有不同等栏目为每个收件人类型

0

我将修改客户和联系人的该定义。客户可以是个人或企业,对吗?在巴西,“pessoajurídica”和“pessoafísica”这两个词在直接(无意识的)翻译中成为“法人”(商业)和“自然人”(个人)。 Google提出了更好的翻译:“法律实体”和“个人”。因此,我们得到一个人表,并有一个'LegalEntity'和'个人'表(如果有足够的属性来证明它 - 这里有很多)。接收器成为Person表的FK。

哪里有联系?他们成为与人联系的桌子。由于联系人是与他人联系的人(例如:我的妻子是我的一些公司的注册联系人,我是客户)。人们可以有联系人。

注意:我使用了'Person'这个词,但您可以将其命名为'Customer'来命名该基表。

相关问题