One lookup table or many lookup tables?

◇◆丶佛笑我妖孽 提交于 2019-12-22 11:05:16

问题


I need to save basic member's data with additional attributes such as gender, education, profession, marital_status, height, residency_status etc.

I have around 15-18 lookup tables all having (id, name, value), all attributes have string values.

Shall I create member's table tbl_members and separate 15-18 lookup tables for each of the above attributes:

tbl_members:

mem_Id
mem_email
mem_password
Gender_Id
education_Id
profession_id
marital_status_Id
height_Id
residency_status_Id

or shall I create only one lookup table tbl_Attributes and tbl_Attribute_Types?

tbl_Attributes:

att_Id
att_Value
att_Type_Id

Example data:

001 - Male - 001
002 - Female - 001
003 - Graduate - 002
004 - Masters - 002
005 - Engineer - 003
006 - Designer - 003

tbl_Attribute_Types:

att_type_Id
att_type_name

Example data:

001 - Gender
002 - Education
003 - Profession

To fill look-up drop-downs I can select something like:

SELECT A.att_id, A.att_value, AT.att_type_name
FROM tbl_Attributes A
INNER JOIN tbl_Attribute_Types AT ON AT.att_type_Id = A.att_type_Id
WHERE att_Type_Id = @att_Type_Id

and an additional table tbl_mem_att_value to save member's attributes and values

tbl_mem_att_value:

mem_id
att_id

Example data for member_id 001, is Male, Masters, Engineer

001 - 001
001 - 004
001 - 005

So my question is shall I go for one lookup table or many lookup tables?

Thanks


回答1:


Never use one lookup table for everything. It will make it more difficult to find things, and it will need to be joined in every query probably multiple times which will mean that it may cause locking and blocking problems. Further in one table you can't use good design to make sure the data type for the descriptor is correct. For instance suppose you wanted a lookup of the state abbreviations which are two characters. If you use a onesize fits all table, then it has to be wide enough for teh largest possible value of any lookup and you lose the possibility of it rejecting an incorrect entry because it is too long. This is a guarantee of later data integrity issues.
Further you can't properly use foreign keys to make sure data entry is limited only to the correct values. This will also cause data integrity issues.

There is NO BENEFIT whatsoever to using one table except a few minutes of dev time (possibly the least important concern in designing a database). There are plenty of negatives.




回答2:


The primary reason for using multiple lookup tables is that you can then enforce foreign key constraints. This is quite important for maintaining relational integrity.

The primary reason for using a single lookup table is so you have all the string values in one place. This can be very useful for internationalization of the software.

In general, I would go with separate reference tables, because relational integrity is generally a more important concern than internationalization.

There are secondary considerations. Many different reference tables are going to occupy more space than a single reference table -- with most of the pages being empty (how much space do you really need to store the gender lookup information?). However, with a relatively small number of reference tables, this is actually a pretty minor concern.

Another consideration in using a single table is that all the reference keys will have different values. This is useful because it can prevent unlikely joins. However, I prevent this problem by naming join keys the same, both for the primary key and the foreign key. So, GenderId would be the primary key in Gender as well as the foreign key column.




回答3:


I've struggled with the same question myself. If the only thing in the lookup table is some sort of code or id and a text value, then it certainly works to just add "attribute id" and throw it all in one table. The obvious advantage is that you then have only one table to create and manage. Searches might possibly be slower because there are more records to search, but presumably you create an index on attribute id + value id. At that point, whether performance is better having one big table or ten small tables probably depends on all sorts of details about how the database engine works and the pattern of access. That's a case where I'd say, Unless in practice it proves to be a problem, don't worry about it.

Two caveats:

One: If you do create a single table, I'd create a code for the attribute name, and then another table to list the codes. Like:

lookup_attribute(attribute_id, attribute_name)
lookup_value(attribute_id, value_id, value_text)

Then the first table has records like

1, 'Gender'
2, 'Marital Status'
3, 'Education'
etc

And the second is

1, 1, 'Male'
1, 2, 'Female'
1, 3, 'Undecided'
2, 1, 'Single'
2, 2, 'Married'
2, 3, 'Divorced'
2, 4, 'Widowed'
3, 1, 'High School'
3, 2, 'Associates'
3, 3, 'Bachelors'
3, 4, 'Masters'
3, 5, 'Doctorate'
3, 6, 'Other'
etc.

(The value id could be unique for all attribute ids or it might only be unique within the attribute id, whatever works for you. It shouldn't matter.)

Two: If there is other data you need to store for some attribute besides just the text of a value, then break that out into a separate table. Like if you had an attribute for, say, "Membership Level", and then the user says that there are different dues for each level and you need to record this, then you have an extra field that applies only to this one attribute. At that point it should become its own table. I've seen systems where they have a couple of pieces of extra data for each of several attributes, and they create a field called "extra data" or some such, and for "membership level" it holds annual dues and for "store name" it holds the city where the store is and for "item number" it holds the number of units on hand of that item, etc, and the system quickly becomes a nightmare to manage.

Update

To retrieve values, let's suppose we have just gender and marital status as lookups. The principle is the same for any others.

So we have the monster lookup table as described above. Then we have the member table with, say

member (member_id, name, member_number, whatever, gender_id, marital_status_id)

To retrieve you just write

select m.member_id, m.name, m.member_number, m.whatever,
  g.value_text as gender, ms.value_text as marital_status
from member m
join lookup_value g on g.attribute_id=1 and g.attribute_value=m.gender_id
join lookup_value ms on ms.attribute_id=2 and ms.attribute_value=m.marital_status_id
where m.member_id=@member_id

You could, alternatively, have:

member (member_id, name, member_number, whatever)
member_attributes (member_id, attribute_id, value_id)

Then you can get all the attributes w

select a.attribute_name, v.value_text
from member_attribute ma
join lookup_attribute a on a.attribute_id=ma.attribute_id
join lookup_value v on v.attribute_id=a.attribute_id and v.value_id=ma.value_id
where ma.member_id=@member_id

It occurs to me as I try to write the queries that there's a distinct advantage to making the value id globally unique: Not only does that eliminate having to specify the attribute id in the join, but it also means that if you do have a field for, say, gender_id, you can still have a foreign key clause on it.



来源:https://stackoverflow.com/questions/27573837/one-lookup-table-or-many-lookup-tables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!