问题描述
|
我正在做这个设计。用户可以说一种或多种语言(限制为五种)。第一语言是母语,其他语言是流利程度。
user 1 speak 3 languages
user_id|first language|secondlanguage|thirdlanguage|fourthlanguage| fifthlanguage
1 english (1) franch(2) portuguese (3) null null
您如何看待这个计划?
听起来有些奇怪,或者这是正确的方法?
解决方法
对此的答案是,它确实取决于。关系纯粹主义者会说这是一个重复的小组,这是一个糟糕的设计,而肮脏的人群会说:“如果您只支持5种语言,那就去做”。但是,实际上-如何确定您永远永远仅支持5种语言?您将要进行哪种查询?假设您想找到所有说英语的人-您的查询将是:
select * from single_user_has_spoken_languages where lang1 = @englishID or lang2 = @englishID or... etc
如果您想找到说英语和法语的人,那么您的where子句会再次增长。如果您添加第六种语言,则每个查询都必须更改。
考虑替代方案:
select distinct UserID from single_user_has_spoken_languages where langID = @englishID
一旦停下来思考一下查询将如何工作,好的设计就会变得更加清晰。
, 我会规范化语言。
因此,例如(为简洁起见,省略了非关键列):
Language Table
id: INT
Single_User Table
id: INT
User_Language Table
user_id: INT
language_id: INT
language_num: SMALLINT
您可以对user_id,language_id和user_id,language_num都设置唯一的约束,以确保没有重复项。您还可以在language_num上设置1到5之间的检查约束,以确保仅选择5种语言。
您还可以选择添加代理键,这将使引用行更加容易。
, 这是\“ correct \”或\“ normaised \”设计的\“ denormalized \”形式,它将具有一个单独的表来存储具有流利顺序列的语言,即:
Table User: User_ud,name,etc
Table Language: user_id,fluency,name
通常出于性能原因使用您的方法,但通常在设计阶段应避免使用。
考虑一下您的设计如何处理添加更多语言插槽或存储该语言说得如何的情况。归一化设计可以轻松解决此问题。你的办法不能。