我的问题与ServiceASpecificField
和ServiceBSpecificField
有关。我觉得这两个字段放置不当,因为对于service A
表中的所有订阅者SubscriberServiceMap
的所有记录,ServiceBSpecificField
将具有空值,反之亦然。
如果我在Subscribers表中移动这两个字段,那么我将遇到另一个问题。所有仅使用service A
的订阅者在Subscribers.ServiceBSpecificField
中都会显示空值。
那么理想情况应该做些什么呢?
答案 0 :(得分:3)
对Service_A and _B
表格进行检查约束,例如:
alter table Service_A add constraint chk_A check (ServiceID = 1);
alter table Service_B add constraint chk_B check (ServiceID = 2);
然后你可以像
一样加入select *
from SubscriberService as x
left join Service_A as a on (a.SubscriberID = x.SubscriberID and a.ServiceID = x.ServiceID)
left join Service_B as b on (b.SubscriberID = x.SubscriberID and b.ServiceID = x.ServiceID)
答案 1 :(得分:2)
这是一个简单的超类型 - 子类型问题,你可以在5NF解决,你不需要EAV或改进的EAV或6NF(完整和最终正确的EAV)。由于ServiceAColumn的值取决于特定订户对服务的订阅,因此它必须位于关联表中。
▶Normalised Data Model◀(内联链接在某些浏览器/版本上不起作用。)
不熟悉关系建模标准的读者可能会发现▶IDEF1X Notation◀很有用。
这是一个普通的Relational Supertype-Subtype结构。这是独家:Service
只有一个子类型。
在此模型中,关系和子类型比其他答案更明确,更受控制。例如。 FK关系特定于Service
子类型,而不是Service
超类型。
Discriminator,用于标识任何超类型行的子类型,是ServiceType
。 ServiceType
不需要在子类型中重复,我们知道子类型表是哪个子类型。
除非您有数百万Services
,否则短代码比无意义的代码更合适。
其他强>
您可能会丢失Id
中的SubscriberService
列,因为它是100%冗余且没有用处。
SubscriberService
的PK为(SubscriberId, ServiceId)
,除非您需要重复的行。
请将列名更改为Subscriber.Id
至SubscriberId
; Service.Id
到ServiceId
。切勿使用Id
作为列名。对于PK和FK,总是使用完整的列名。当您开始编码时,您的相关性将变得清晰。
第六范式或EAV
在添加具有新属性的新服务时添加列和表在关系数据库中是必要的,并且您保留了大量的控制和完整性。
如果您不希望每个新服务添加新表,那么请使用EAV或6NF,但请确保您在关系数据库中可以使用正常控件(类型安全)和数据和参照完整性。 EAV通常在没有适当的关系控制和完整性的情况下实现,这会导致许多问题。这是关于该主题的question/answer。如果你确实如此,并且该问题中的数据模型不够详细,请告诉我,我将为您提供一个特定于您的要求的数据模型(我上面提供的DM是纯5NF,因为这是对原始问题的完全要求。)
答案 2 :(得分:1)
执行此操作的简单方法是问自己:这些列的值是否根据订阅(SubscriberServiceMap
表)或服务而有所不同?
如果“服务A”的每个订阅者都具有ServiceASpecificField
的相同值,则必须将其移至Services
表。
您预计会有多少这样的字段? ServiceASpecificField,ServiceBSpecificField,C,D ......等等?如果数字相当大,你可以选择EAV model,这将涉及创建另一个表。
答案 3 :(得分:-1)
如果ServiceSpecificField的值同时取决于服务和订阅者以及所有订阅者 - 服务对的字段类型 - 是相同的(就像我在示例中看到的那样 - 两个字段的varchar(50)),那么我会仅更新SubscriberSerivceMap表:
table SubscriberSerivceMap:
Id
SubscriberId
ServiceId
SpecificField
此类表的示例:
Id SubscriberId Service Id SpecifiedField
1 1 1 sub1_serv1
2 1 2 sub1_serv2
3 2 1 sub2_serv1
4 2 2 sub2_serv2