6 mysql postgresql database-design
我们正在构建的软件有“客户”。客户可以是个人或组织。
我真的很想为此创建一个最佳模式。
我有这些考虑。
我希望应用程序能够适当地扩展,因此架构应该适合此选择。
我正在尝试实现以下目标。
SELECT * FROM Customers + a few joins.
1. Person | NULL | John Doe | Primary Organisation Contact | Primary Address
2. Organisation | Acme Ltd | Jane Doe | Primary Organisation Contact | Primary Address
Run Code Online (Sandbox Code Playgroud)
我应该如何创建一个最佳模式来关联上述内容?
我附上了一个粗略的 Visual Schema 层次结构 - 我知道我离得很远!!我确定我犯了错误。
是否有可能根据是个人还是组织来获得一组已婚结果?
将个人和联系人/地址加入客户很简单,但您如何加入组织的主要联系人/地址?
有没有更简单的方法来实现我的蜘蛛图外观架构。??
Den*_*rdy 12
实际构建了几个与联系人和公司的应用程序的一些见解。
首先,您的大纲中缺少几个用例。在我多年来遇到的五颜六色的那些你不一定涵盖的:
其次,由于您的提纲提到了客户,请注意客户可能是公司或(自然人)。您似乎根据您的图表涵盖了该部分,所以让我们继续。
如果您的下一步是添加与会计相关的任何内容,例如“订单”表,请注意任何与会计相关的内容都与特定时间点的公司、联系人、产品、价格等相关联。这些细节可以以各种丰富多彩的方式演变,一个常见的设计错误是创建完美的规范化设计并假设您只会根据需要更新表格。大不。如果税务员要求您打印发票,而您的 IT 说公司 XYZ 的价格为 P,而会计以 Q 的价格预订了公司 ABC,那么您就非常非常糟糕。并且不要让我开始归档/关闭的年度帐户和报告由于类似的设计错误而发生变化。
第三,要非常、非常、非常警惕您可能因过度规范化而引入的 UI/UX 问题。如果它不像典型用户手中的应用程序那样工作(阅读:Outlook),那么当乔获得新工作时,您将成为一名训练有素的秘书,无法将 XYZ 的每个员工的公司改为 ABC。我实际上已经看到这种情况发生,这不是一个漂亮的景象。(她保住了她的工作,以防你想知道。)
最后,不要让我开始合并不可避免的重复公司、联系人和许多其他不可能出现的丰富多彩的事情。保持这些放在心上,确保您的架构是非常,非常宽容的,因为它会发生。
现在……在实践中……
就个人而言,在这种情况下,我实际上对规范化视而不见。联系人/公司是其中一种情况,其中在学校教授的数据库设计和精美的规范化数据会导致资源占用、过于复杂的查询和极其复杂的 UI 形式的麻烦。无论如何,恕我直言,这不是正确的做法。
首先创建一个联系人表,填写诸如姓名、显示名称(如果需要)、公司名称、地址、电话、手机、电子邮件、email2、秘书姓名、秘书电话等字段。如果在 Outlook 中创建联系人时可用,它可能属于那里。
你会注意到我没有提到公司表。那是因为您通常不希望您的联系人表和公司表之间有任何强关联。如果需要,请添加一个,并在 company_name 之外添加一个 copmany_id。但是,在 delete set null 上使它成为外键。并确保在数据库级别与 company_name 保持非常非常松散的联系。在前端级别维护它——而不是其他任何地方。这将防止秘书无意中更改多个联系人的公司。
保持理智。任何可能合理地出现在列表中的东西(即 select * from contacts where ... limit 10)、被查询或经常有用的东西都应该在表中。没有加入,纳达。查询,遍历结果,完成。
如果您真的想要在那里添加更多垃圾,您有两种选择。
一种是创建一个 extra_contact_details 表。它可以是 EAV 表,也可以是公司名称、地址、电话等字段的全部负载,也可以是规范化的零碎内容。无论您采取哪种选择,都不要过度。当您创建 UI 时,这两种方法都会创建额外的(可能很复杂)查询,以及大量棘手的编程问题。这里绝对关键的是,如果你走这条路,一个一直使用 Outlook 的秘书需要理解它。
另一个,我实际上会预先推荐,是在联系人表中添加一个名为“extra_contact_details”的文本字段并开始使用它。根本没有标准化。一组主要细节。经常使用的次要细节。任何额外的纯文本。秘书收到。最终用户得到它。完毕。
最后,如果您需要在给定的时间点存储任何数据的一个版本,请确保复制任何关键细节的值——请阅读:无论您需要按插入时的原样打印它。
伙计,我希望数据库书籍能在第一章中介绍派对模型。
如果您的时间对您很有价值,请阅读 Hay 的 Enterprise Model Patterns 或 Silverston 的 Data Model Resource Book。可以在 Safari 上找到便宜的 em。
另请阅读表继承:
http://martinfowler.com/eaaCatalog/singleTableInheritance.html
如果您不喜欢空值,请使用类表继承。
一方代表人、组织、自动化代理:
Party
id
name
Individual : Party
Organization : Party
AutomatedAgent : Party
Run Code Online (Sandbox Code Playgroud)
客户是一方扮演的角色。例如,某人可能是您的供应商,您雇用他们作为员工,解雇他们,然后他们成为您的客户。
您可以根据他们是否向您下销售订单,或使用 PartyRole 将他们声明为客户来推导出他们的“客户”。
PartyRelationship 表示各方之间的关系:
PartyRelationship
fromParty
toParty
fromDate
toDate (nullable)
OrganizationContact : PartyRelationship
Employment : PartyRelationship
Run Code Online (Sandbox Code Playgroud)
地址代表物理地址和虚拟地址:
Address
id
EmailAddress : Address
emailAddress
WebAddress : Address
url
TelephoneNumber : Address
telephoneNumber
MailingAddress : Address
suiteOrApartment
street
city
zip
Run Code Online (Sandbox Code Playgroud)
人们有多种联系方式:
ContactMethod
party
address
fromDate
toDate (nullable)
telephoneExtension (nullable)
Run Code Online (Sandbox Code Playgroud)
我强烈推荐使用像 Hibernate 这样的工具,因为它会让你的生活更轻松。
小智 1
像这样的事情怎么办?
addresses
id unsigned int(P)
street1 varchar(50)
street2 varchar(50)
city_id unsigned int(F cities.id)
zip varchar(6)
lat double
lon double
cities
id unsigned int(P)
state_id unsigned int(F states.id)
name varchar(50)
countries
id char(2)(P)
iso3 char(3)(U)
iso_num char(3)(U)
name varchar(45(U)
customers
id unsigned int(P)
parent_id unsigned int(F customers.id) (Allow NULL)
name varchar(50) // John Doe, ABC Company, etc.
customers_addresses
id unsigned int(P)
customer_id unsigned int(F customers.id)
address_id unsigned int(F addresses.id)
customers_email_addresses
id unsigned int(P)
customer_id unsigned int(F customers.id)
email_address_id unsigned int(F email_addresses.id)
customers_phone_numbers
id unsigned int(P)
customer_id unsigned int(F customers.id)
phone_number_id unsigned int(F phone_numbers.id)
email_addresses
id unsigned int(P)
address varchar(255)
phone_numbers
id unsigned int(P)
area_code char(3)
exchange char(3)
station char(4)
extension varchar(10)
states
id unsigned int(P)
country_id char(2)(F countries.id)
code char(2)
Run Code Online (Sandbox Code Playgroud)
电话号码和邮政编码适用于北美国家/地区,而对于其他国家/地区则必须进行更改。
以下是该customers
表的一些示例数据:
+----+-----------+---------------+
| id | parent_id | name |
+----+-----------+---------------+
| 1 | NULL | ABC Company |
| 2 | NULL | XYZ Company |
| 3 | 1 | John Doe |
| 4 | 1 | Jane Doe |
| 5 | 2 | John Q Public |
| 6 | NULL | JKL Company |
+----+-----------+---------------+
Run Code Online (Sandbox Code Playgroud)
组织始终有一个NULL
parent_id。个人可以有一个NULL
parent_id(当他们不与组织关联时)或非NULL
parent_id(当他们与组织关联时)。您的特定需求可能需要其他更改......
SQL 示例:
SELECT * FROM customers c
LEFT JOIN customers_addresses ca ON c.id = ca.customer_id
LEFT JOIN customers_email_address ce ON c.id = ce.customer_id
LEFT JOIN customers_phone_numbers cp ON c.id = cp.customer_id
LEFT JOIN cities ON ca.city_id = cities.id
LEFT JOIN states ON cities.state_id = states.id
LEFT JOIN countries ON states.country_id = countries.id
WHERE c.id = 1
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14389 次 |
最近记录: |