2010-10-20 40 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'來命名該基表。

相關問題