How to represent many similar attributes of an entity in a database?

流过昼夜 提交于 2020-01-06 07:00:16

问题


Let's say I'm building a website about cars. The car entity has a lot of enum-like attributes:

  • transmission (manual/automatic)
  • fuel (gasoline/diesel/bioethanol/electric)
  • body style (coupe/sedan/convertible/...)
  • air conditioning (none/simple/dual-zone)
  • exterior color (black/white/gray/blue/green/...)
  • interior color (black/white/gray/blue/green/...)
  • etc.

The list of these attributes is likely to change in the future. What is the optimal way to model them in the database? I can think of the following options but can't really decide:

  • use fields in the car table with enum values
    • hard to add more columns later, probably the fastest
  • use fields in the car table that are foreign keys referencing a lookup table
    • hard to add more colums later, somewhat slower
  • create separate tables for each of those attributes that store the possible values and another table to store the connection between the car and the attribute value
    • easy to add more possible values later, even slower, seems to be too complicated

回答1:


Depending upon the number of queries and size of the databases you could either:

  1. Make wide tables
  2. Make an attibutes table and a car_attributes table where: cars -> car_attributes -> attributes

#1 will make faster, easier queries due to less joins, but #2 is more flexible




回答2:


Idealy is to create a relational database. Each table from DB should be represented by a class, as in hibernate. You should make 2 tables for the car. One for the interior and one for the exterior of the car. If you want to add extra features, you just add more columns.




回答3:


Now here is a (very basic) EAV model:

DROP TABLE IF EXISTS example.zvalue CASCADE;
CREATE TABLE example.zvalue
        ( val_id SERIAL NOT NULL PRIMARY KEY
        , zvalue varchar NOT NULL
        , CONSTRAINT zval_alt UNIQUE (zvalue)
        );
GRANT SELECT ON TABLE example.zvalue TO PUBLIC;

DROP TABLE IF EXISTS example.tabcol CASCADE;
CREATE TABLE example.tabcol
        ( tabcol_id SERIAL NOT NULL PRIMARY KEY
        , tab_id BIGINT NOT NULL REFERENCES example.zname(nam_id)
        , col_id BIGINT NOT NULL REFERENCES example.zname(nam_id)
        , type_id varchar NOT NULL
        , CONSTRAINT tabcol_alt UNIQUE (tab_id,col_id)
        );
GRANT SELECT ON TABLE example.tabcol TO PUBLIC;

DROP TABLE IF EXISTS example.entattval CASCADE;
CREATE TABLE example.entattval
        ( ent_id BIGINT NOT NULL
        , tabcol_id BIGINT NOT NULL REFERENCES example.tabcol(tabcol_id)
        , val_id BIGINT NOT NULL REFERENCES example.zvalue(val_id)
        , PRIMARY KEY (ent_id, tabcol_id, val_id)
        );
GRANT SELECT ON TABLE example.entattval TO PUBLIC;

BTW: this is tailored to support system catalogs; you might need a few changes.




回答4:


This is really a duplicate of this dba.SE post:

https://dba.stackexchange.com/questions/27057/model-with-variable-number-of-properties-of-different-types

Use hstore, json, xml, an EAV pattern, ... see my answer on that post.




回答5:


It is up to the admin UI you need to support:

  • If there is an interface to manage for example the types of a transmission you should store this in a separate entity. (your option 3)
  • If there is no such interface the best would be to store in like enumerable type values. When you need another one(for example 'semi-automatic' for the transmission) you will add this only in the DB schema, as a matter of fact this will be the easiest to support and fastest to execute



回答6:


I would create create table CarAttributes with column AttributeID,CarID,PropertyName,PropertyValue. When reslut set is returned we save it in IDictionary. It will allow you to add as many rows as you need without adding new columns.



来源:https://stackoverflow.com/questions/13425574/how-to-represent-many-similar-attributes-of-an-entity-in-a-database

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