2009-03-15 30 views
17

Mỗi Customer có địa chỉ thực và địa chỉ gửi thư tùy chọn. Cách ưa thích của bạn để mô hình hóa điều này là gì?Cách tốt nhất để mô hình Khách hàng <--> Địa chỉ

Lựa chọn 1. Customer có chính nước ngoài để Address

 
    Customer (id, phys_address_id, mail_address_id) 
    Address (id, street, city, etc.) 

Lựa chọn 2. Customer có một-nhiều mối quan hệ với Address, trong đó có một lĩnh vực để mô tả các loại địa chỉ

 
    Customer (id) 
    Address (id, customer_id, address_type, street, city, etc.) 

Tùy chọn 3. Thông tin địa chỉ không được chuẩn hóa và lưu trữ trong Customer

 
    Customer (id, phys_street, phys_city, etc. mail_street, mail_city, etc.) 

Một trong những mục tiêu quan trọng của tôi là đơn giản hóa ánh xạ đối tượng-quan hệ, vì vậy tôi đang hướng tới phương pháp đầu tiên. Quan điểm của bạn là gì?

Trả lời

10

Tôi có xu hướng hướng tới phương pháp đầu tiên cho tất cả các lý do bình thường hóa thông thường. Cách tiếp cận này cũng giúp dễ dàng thực hiện làm sạch dữ liệu trên các chi tiết gửi thư.

Nếu bạn đang có khả năng sẽ cho phép nhiều địa chỉ (mail, khu dân cư, vv) hoặc muốn để có thể sử dụng ngày có hiệu lực, hãy xem xét cách tiếp cận này

 
    Customer (id, phys_address_id) 
    Cust_address_type (cust_id, mail_address_id, address_type, start_date, end_date) 
    Address (id, street, city, etc.) 
+0

tại sao bạn sẽ tách riêng cust_address_type và địa chỉ? Các thông tin chứa trong cả hai có thể ngồi trên một bảng mà không có bất kỳ vấn đề. Tôi thấy không có lợi ích cho 3 bảng khi 2 sẽ làm. – JM4

+0

Vì sau đó bạn có thể có 1 hoặc nhiều địa chỉ cho mỗi khách hàng, ví dụ: thanh toán, phân phối, v.v. Ngoài ra, bạn có thể dễ dàng theo dõi lịch sử thông qua các trường ngày tháng. Bạn có thể có nhiều khách hàng tại cùng một địa chỉ và coi mỗi khách hàng là một thực thể nhưng việc thay đổi địa chỉ cho một nhu cầu không ảnh hưởng đến người khác. – Karl

+0

Mô hình này cũng phù hợp với các tình huống rất tốt nơi bạn có danh sách hầu hết các địa chỉ và chỉ định chúng (ví dụ: nếu bạn đã mua danh sách địa chỉ từ bưu điện hoặc tương tự). Hoặc nơi mà cơ sở dữ liệu của bạn đủ lớn để có hầu hết các địa chỉ trong khu vực của bạn. – Karl

3

Tùy chọn thứ hai có thể là cách tôi sẽ thực hiện. Và trên cơ hội nó sẽ cho phép người dùng thêm địa chỉ bổ sung '(Nếu bạn muốn để họ làm điều đó), họ có thể chuyển đổi giữa lúc sẽ cho vận chuyển và như vậy.

3

Tôi muốn # 1. Bình thường hóa tốt và truyền đạt ý định rõ ràng. Mô hình này cũng cho phép cùng một đối tượng địa chỉ (hàng) được sử dụng cho cả hai địa chỉ, điều mà tôi thấy là khá có giá trị. Nó quá dễ bị lạc trong việc sao chép thông tin này quá nhiều.

+1

Tôi muốn được quan tâm đến cách thực hiện điều này trong giao diện người dùng. Tôi đã xây dựng một hệ thống cho phép các đối tượng địa chỉ được chia sẻ, nhưng người dùng không nhận được khái niệm. – cdonner

+0

Tôi nghĩ bạn là người thứ hai, dựa trên mô tả của bạn. Tất cả chúng đều được đánh dấu # 1 – singpolyma

+0

@singpolyma No. Câu hỏi được chỉnh sửa ngay bây giờ, quá .. – krosenvold

1

Tôi sẽ chọn tùy chọn đầu tiên. Trong những tình huống này tôi rất mệt mỏi với YAGNI (bạn sẽ không cần nó). Tôi không thể đếm số lần tôi đã xem xét các lược đồ mà đã có một đến nhiều bảng "chỉ cần incase" được nhiều tuổi. Nếu bạn chỉ cần hai, chỉ cần sử dụng tùy chọn đầu tiên; nếu yêu cầu thay đổi trong tương lai, hãy thay đổi nó sau đó.

1

Giống như trong nhiều trường hợp: Nó phụ thuộc.

Nếu khách hàng của bạn đối phó với nhiều địa chỉ thì mối quan hệ nhiều người sẽ phù hợp. Bạn có thể giới thiệu một lá cờ trên địa chỉ báo hiệu nếu một địa chỉ là cho lô hàng hoặc hóa đơn, vv Hoặc bạn lưu trữ các loại địa chỉ khác nhau trong các bảng khác nhau và có nhiều mối quan hệ với một khách hàng.

Trong trường hợp bạn chỉ cần biết một địa chỉ của khách hàng tại sao bạn sẽ mô hình hóa thành nhiều? Mối quan hệ một-một sẽ đáp ứng nhu cầu của bạn ở đây.

Quan trọng: Không chuẩn hóa chỉ khi bạn gặp sự cố về hiệu suất.

1

Tùy chọn 3 quá hạn chế và không thể mở rộng tùy chọn 1 để cho phép các loại địa chỉ khác mà không thay đổi giản đồ. Tùy chọn 2 rõ ràng là linh hoạt nhất và do đó là lựa chọn tốt nhất.

+0

Tôi đồng ý rằng nó là linh hoạt nhất, nhưng nó có đáng để cân bằng trong ORM phức tạp? –

1

tôi sẽ đi với tùy chọn 1. Nếu bạn muốn, bạn thậm chí có thể sửa đổi nó một chút để giữ một lịch sử địa chỉ:

Customer (id, phys_address_id, mail_address_id) 
Address (id, customer_id, start_dt, end_dt, street, city, etc.) 

Nếu thay đổi địa chỉ, chỉ kết thúc ngày địa chỉ hiện tại và thêm một bản ghi mới trong bảng Address. phys_address_idmail_address_id luôn trỏ đến địa chỉ hiện tại.

Bằng cách đó bạn có thể giữ một lịch sử của địa chỉ, bạn có thể có nhiều địa chỉ gửi thư lưu trữ trong cơ sở dữ liệu (với mặc định trong mail_address_id), và nếu địa chỉ vật lý và địa chỉ gửi thư là giống hệt nhau, bạn sẽ chỉ cần trỏ phys_address_idmail_address_id tại cùng một bản ghi.

+0

-1 - Với thiết kế này, bạn đã có sự phụ thuộc hai chiều giữa bảng Địa chỉ và Khách hàng, làm cho lược đồ cơ sở dữ liệu trở nên giòn hơn, đồng thời không thêm lợi ích thực sự. –

6

Một thực tế quan trọng bạn có thể cần cân nhắc (tùy thuộc vào miền sự cố của bạn) là mọi người thay đổi địa chỉ và có thể muốn thông báo trước cho bạn về thay đổi địa chỉ của họ; điều này chắc chắn đúng đối với các công ty tiện ích, công ty viễn thông, v.v.

Trong trường hợp này, bạn cần có cách lưu trữ nhiều địa chỉ cho khách hàng với ngày hiệu lực để địa chỉ có thể được thiết lập trước và tự động chuyển đổi điểm chính xác. Nếu đây là yêu cầu, thì biến thể trên (2) là cách hợp lý duy nhất để mô hình hóa nó, ví dụ:

Customer (id, ...) 
Address (id, customer_id, address_type, valid_from, valid_to) 

Mặt khác, nếu bạn không cần phải để phục vụ cho việc này (và bạn chắc chắn sẽ không trong tương lai) sau đó có thể (1) là đơn giản để quản lý vì nó dễ dàng hơn để duy trì tính toàn vẹn của dữ liệu vì không có vấn đề gì với việc đảm bảo chỉ có một địa chỉ cùng loại tồn tại và các kết nối trở nên đơn giản hơn vì chúng chỉ có trên một trường.

Vì vậy, hoặc (1) hoặc (2) là tốt tùy thuộc vào việc bạn cần di chuyển nhà hay không, nhưng tôi sẽ tránh (3) vì bạn đang lặp lại định nghĩa địa chỉ trong bảng và bạn sẽ phải thêm nhiều cột nếu bạn thay đổi địa chỉ trông như thế nào. Nó có thể có hiệu suất cao hơn một chút, nhưng thành thật mà nói khi bạn giao dịch với các kết nối được lập chỉ mục phù hợp trong cơ sở dữ liệu quan hệ thì sẽ không có nhiều thứ để đạt được và có thể chậm hơn trong một số trường hợp mà bạn không cần địa chỉ như kích thước kỷ lục cho một khách hàng sẽ lớn hơn.

+0

Bảng địa chỉ này chỉ gắn với khách hàng không phải địa chỉ đặt hàng hoặc địa chỉ văn phòng. – kta

2

Khi trả lời các loại câu hỏi tôi muốn sử dụng các phân loại của DDD. Nếu đó là một thực thể, nó phải có một ID riêng biệt, nếu đó là một đối tượng giá trị nó không nên.

2

Trong hầu hết mã, tôi viết ngày nay mọi khách hàng đều có một và chỉ một vị trí thực tế. Đây là pháp nhân nuôi ong đối tác kinh doanh của chúng tôi. Do đó tôi đặt đường phố, thành phố vv trong đối tượng/bảng của khách hàng. Thường thì đây là điều đơn giản nhất có thể hoạt động và nó hoạt động.

Khi cần thêm địa chỉ gửi thư, tôi đặt nó vào một đối tượng/bảng riêng để không làm xáo trộn đối tượng khách hàng nhiều.

Trước đó trong sự nghiệp, tôi đã chuẩn hóa như điên khi có đơn đặt hàng tham chiếu một khách hàng tham chiếu địa chỉ giao hàng. Điều này làm cho mọi thứ "sạch" nhưng chậm và không thích hợp để sử dụng. Ngày nay tôi sử dụng một đối tượng đơn đặt hàng chỉ chứa tất cả thông tin địa chỉ. Tôi thực sự xem xét điều này tự nhiên hơn vì khách hàng có thể thay đổi địa chỉ (mặc định?) Của mình, nhưng địa chỉ của lô hàng gửi trong năm 2007 phải luôn như cũ - ngay cả khi khách hàng di chuyển trong năm 2008.

Hiện tại chúng tôi đang triển khai VerySimpleAddressProtocol trong dự án tiêu chuẩn hóa các trường được sử dụng.

+1

Thay đổi dữ liệu địa chỉ của bạn không hợp lệ. Một hàng địa chỉ duy nhất sẽ không thay đổi, nếu được tham chiếu trong các thực thể mà nó không được thay đổi. Trong trường hợp địa chỉ phải thay đổi một bản ghi mới phải được tạo, nếu nó bằng với bản ghi hiện có, hãy sử dụng bản ghi hiện có. Bạn bảo tồn lịch sử. Chúng tôi đã sử dụng phương pháp này trong một công ty bao thanh toán và sản phẩm thương mại điện tử. Bạn có thể sử dụng các quy tắc phụ thuộc ngôn ngữ để làm sạch dữ liệu đầu vào của người dùng để đạt được chất lượng so sánh rất tốt. Hoặc sử dụng các nhà cung cấp bên ngoài như các công ty bưu chính. – djmj

3

Chúng tôi đang di chuyển về phía trước với một mô hình như thế này:

Person (id, given_name, family_name, title, suffix, birth_date) 
Address (id, culture_id, line1, line2, city, state, zipCode, province, postalCode) 
AddressType (id, descriptiveName) 
PersonAddress (person_id, address_id, addressType_id, activeDates) 

Hầu hết có thể xem xét quá mức này. Tuy nhiên, một chủ đề chung không thể phủ nhận giữa các ứng dụng chúng tôi phát triển là họ sẽ có một số thực thể cơ bản này - Con người, Tổ chức, Địa chỉ, Số điện thoại, v.v. - và tất cả họ đều muốn kết hợp chúng theo nhiều cách khác nhau. Vì vậy, chúng tôi đang xây dựng trong một số khái quát hóa phía trước rằng chúng tôi chắc chắn 100% chúng tôi có trường hợp sử dụng cho.

Bảng địa chỉ sẽ tuân theo lược đồ kế thừa bảng cho mỗi phân cấp để phân biệt các địa chỉ dựa trên văn hóa; do đó địa chỉ ở Hoa Kỳ sẽ có trạng thái và trường zip, nhưng địa chỉ Canada sẽ có một tỉnh và mã bưu điện.

Chúng tôi sử dụng bảng kết nối riêng để "cung cấp" cho một người một địa chỉ. Điều này giữ các thực thể khác của chúng tôi - Người & Địa chỉ - không có quan hệ với các thực thể khác khi trải nghiệm của chúng tôi có xu hướng làm phức tạp các vấn đề trên đường. Nó cũng làm cho nó đơn giản hơn nhiều để kết nối các thực thể Address với nhiều loại thực thể khác (People, Organization, etc.) và với các thông tin ngữ cảnh khác nhau liên kết với liên kết (như activeDates trong ví dụ của tôi).

+0

+1 Đó là thiết kế tôi đã đăng. Tôi đã sử dụng bảng kết nối đó để thúc đẩy rất nhiều chức năng. Làm sạch dữ liệu ngay cả những người gửi thư tiếp thị. Tính năng này hữu ích khi những người muốn báo cáo có thể thấy khách hàng nào được gửi đến chiến dịch cuối cùng, v.v. – Taptronic

+0

cho đến nay đây là giải pháp tốt nhất. – kta

4

Tôi nhận thấy rằng thiết kế "khách hàng" âm thanh ban đầu thường sau đó bị hỏng vì: trước đây xử lý doanh nghiệp khi khách hàng phát triển xử lý các nhân viên cá nhân làm khách hàng hoặc khách hàng sẽ thay đổi/chia/hợp nhất địa chỉ hoặc doanh nghiệp thay đổi tên nhưng chúng tôi vẫn muốn hợp nhất tổng hiệu suất cũ và mới hoặc địa chỉ giao hàng và địa chỉ thanh toán hiện phải được mở rộng để bao gồm địa chỉ hỗ trợ hoặc người vận hành quên hoặc nhầm lẫn một mục đích địa chỉ cho một địa chỉ khác, hoặc khách hàng chỉ muốn sử dụng địa chỉ giao hàng đặc biệt tạm thời hoặc v.v.

Kết quả là tôi đã từ bỏ ý tưởng về tệp khách hàng chính hoàn toàn. Thay vào đó, thông tin tên/công ty/địa chỉ không bao giờ là bản ghi chính (ngoại trừ các ứng dụng như thanh toán tiện ích hoặc thuế bất động sản không thể chỉnh sửa địa chỉ cụ thể vào địa chỉ khác), chúng chỉ là các trường biểu thị địa chỉ liên hệ đang sử dụng AT A PARTICULAR POINT IN TIME, thường bên trong một thứ gì đó giống như hồ sơ bán hàng. Mỗi đơn đặt hàng được liên kết với đơn đặt hàng trước đó và tiếp theo cho khách hàng đó, ngay cả khi khách hàng thay đổi tên hoặc địa chỉ của họ. Ưu điểm là tất cả các đơn đặt hàng có thể được tổng hợp/tổng cộng/phân tích trong toàn bộ lịch sử giao dịch của khách hàng, mặc dù mỗi đơn hàng có thể thay đổi tên hoặc địa chỉ liên hệ. Nó có phần phản trực giác, đặc biệt là khi cố gắng làm hài lòng các nhà thiết kế db, nhưng nó kết thúc rất linh hoạt và thuận tiện.

Ví dụ: khi khách hàng X đặt hàng đầu tiên, không có bản ghi khách hàng nào được tạo. Thay vào đó, một hồ sơ bán hàng được tạo ra có chứa thông tin tên/công ty/địa chỉ cần thiết có hiệu lực tại thời điểm đặt hàng. Khi khách hàng X đặt hàng thứ hai của mình, chúng tôi không tìm kiếm tệp khách hàng, chúng tôi tìm kiếm tệp đơn đặt hàng, sau đó sao chép/chuỗi nó để tạo đơn đặt hàng thứ hai của mình. Nếu anh ta muốn thay đổi tên/thông tin về công ty/địa chỉ của mình, thì chúng tôi chỉ chỉnh sửa các trường đó theo thứ tự bán hàng số 2 và thứ tự bán hàng số 1 không thay đổi. Bây giờ anh ấy có thể định vị theo một trong hai biến thể (thứ tự 1 hoặc 2).

Đối với những cân nhắc khác khi cố gắng để quyết định xem hai hồ sơ khách hàng đang thực sự giống nhau, thấy http://semaphorecorp.com/mpdd/mpdd.html

0

tốt chủ đề. Tôi đã dành một thời gian chiêm ngưỡng giản đồ phù hợp nhất và tôi đã kết luận rằng giải pháp quentin-starin là tốt nhất ngoại trừ tôi đã thêm các trường start_dateend_date vào bảng PersonAddress của mình.Tôi cũng đã quyết định thêm ghi chú, hoạt độngđã xóa.

bị xóa là dành cho chức năng xóa mềm vì tôi nghĩ tôi không muốn mất dấu vết của các địa chỉ trước đó chỉ đơn giản bằng cách xóa bản ghi khỏi bảng giao lộ. Tôi nghĩ rằng đó là khá khôn ngoan và một cái gì đó khác có thể muốn xem xét. Nếu không làm theo cách này, nó có thể được để lại để sửa đổi giấy hoặc tài liệu điện tử để cố gắng để theo dõi thông tin địa chỉ (một cái gì đó tốt nhất tránh được).

ghi chú Tôi nghĩ là một thứ gì đó của một yêu cầu nhưng điều đó có thể chỉ là sở thích. Tôi đã dành thời gian trong các bài tập chèn lấp xác minh địa chỉ trong cơ sở dữ liệu và một số địa chỉ có thể rất mơ hồ (chẳng hạn như địa chỉ nông thôn) mà tôi nghĩ rằng nó rất hữu ích để ít nhất cho phép ghi chú về địa chỉ đó được tổ chức tại địa chỉ ghi.

Một điều tôi muốn nghe ý kiến ​​là lập chỉ mục duy nhất của bảng (một lần nữa, hãy tham khảo bảng có cùng tên trong ví dụ của quentin-starin. Bạn có nghĩ rằng nó nên là chỉ mục duy nhất Điều này có vẻ hợp lý nhưng vẫn có thể khó ngăn chặn dữ liệu trùng lặp bất kể khi mã bưu chính/mã zip không phải lúc nào cũng duy nhất cho một thuộc tính duy nhất. , các trường tỉnh và thành phố được điền từ dữ liệu tham chiếu (chúng nằm trong mô hình của tôi), sự khác biệt chính tả trong các dòng địa chỉ có thể không khớp. Cách duy nhất để tránh điều này có thể là chạy một hoặc một số truy vấn DB từ các trường biểu mẫu đến để xem liệu một bản sao có thể đã được tìm thấy hay chưa. Một biện pháp an toàn khác sẽ cung cấp cho người dùng ption của việc lựa chọn từ địa chỉ trong cơ sở dữ liệu đã được liên kết với người đó và sử dụng nó để tự động điền. Tôi nghĩ rằng đây có thể là một trường hợp mà bạn chỉ có thể hợp lý và có biện pháp phòng ngừa để ngăn chặn trùng lặp nhưng chỉ chấp nhận nó có thể (và có thể sẽ) xảy ra sớm hay muộn.

Khía cạnh rất quan trọng khác của điều này đối với tôi là chỉnh sửa trong tương lai của địa chỉ bản ghi bảng. Cho phép nói rằng bạn có 2 người cả niêm yết tại địa chỉ: -

11 Dù đường Dù thành phố Z1P C0D3

nên nó không được coi là nguy hiểm cho phép địa chỉ cùng một kỷ lục bảng để được giao cho các đơn vị khác nhau (người, công ty)? Sau đó, giả sử người dùng nhận ra một trong những người này sống ở 111 Phố Dù và có lỗi đánh máy. Nếu bạn thay đổi địa chỉ đó, nó sẽ thay đổi nó cho cả hai thực thể. Tôi muốn tránh điều đó. Đề nghị của tôi sẽ có mô hình trong MVC (trong trường hợp của tôi, PHP Yii2) tìm kiếm địa chỉ hiện tại ghi lại khi địa chỉ mới được tạo được biết là có liên quan đến khách hàng đó (SELECT * FROM address INNER JOIN personaddress ON personaddress .address_id = address.id WHERE personaddress.person_id = {người hiện đang được chỉnh sửa ID}) và cung cấp cho người dùng tùy chọn sử dụng bản ghi đó thay vào đó (như đã được đề xuất cơ bản ở trên).

tôi cảm thấy liên kết cùng một địa chỉ cho nhiều thực thể khác nhau chỉ là chuốc lấy phiền vì nó có thể là một trường hợp từ chối chỉnh sửa sau này của các địa chỉ kỷ lục (không thực tế) hoặc rủi ro mà các chỉnh sửa trong tương lai của kỷ lục có thể làm hỏng dữ liệu liên quan đến các pháp nhân khác bên ngoài địa chỉ địa chỉ đang được chỉnh sửa.

Tôi rất thích nghe suy nghĩ của mọi người.

Các vấn đề liên quan