Are there any options to a join table for many-to-many associations?

后端 未结 2 587
抹茶落季
抹茶落季 2020-12-20 06:35

Let\'s say I have two tables with data that isn\'t supposed to change through the use of my application (i.e. domain tables) for something like the model of a car

2条回答
  •  暖寄归人
    2020-12-20 07:01

    • If models don't share colour groups then the design would be one table:

      model [model] comes in color [color]
      
    • If models share colour groups then have two tables:

      model [model] comes in the colors of group [group]
      group [group] has color [color]
      

      These tables join with projection to the first table:

      SELECT model, color FROM model_group NATURAL JOIN group_color
      
    • If a model can have exceptional available and/or unavailable colours in addition to or instead of a group then have exception tables. A table's group is now its default colours (if any):

      model [model] has default color group [group]
      group [group] has color [color]
      model [model] is exceptionally available in color [color]
      model [model] is exceptionally unavailable in color [color]
      

      The exception tables are then respectively UNIONed with and MINUSed/EXCEPTed from a JOIN-plus-PROJECT/SELECT to give the first table:

      SELECT group, color FROM model_default NATURAL JOIN group_colour
      EXCEPT SELECT * FROM model_unavailable
      UNION SELECT * FROM model_available
      

    "Redundancy" is not about values appearing in multiple places. It is about multiple rows stating the same thing about the application.

    Every table (and query expression) has an associated fill-in-the-(named-)blanks statement template (aka predicate). The rows that make a true statement go in the table. If you have two independent predicates then you need two tables. The relevant values go in the rows of each one.

    Re rows making statements about the application see this. (And search my other answers re a table's "statement" or "criterion".) Normalization helps because it replaces tables whose rows state things of the form "... AND ..." by other tables that state the "..." separately. See this and this.

    If you share groups and only use a single two-column table for model and color then its predicate is:

    FOR SOME group
        model [model] comes in the colors of group [group]
    AND group [group] has color [color]
    

    So the second bullet removes a single "AND" from this predicate, ie the source of a "multivalued dependency". Otherwise if you change a model's group or a group's colours then you have to simultaneously consistently change multiple rows. (The point is to reduce errors and complexity from redundancy, not save space.)

    If you don't want to repeat the strings for implementation(-dependent) reasons (space taken or speed of operations at the expense of more joins) then add a table of name ids and strings and replace your old name columns and values by id columns and values. (That's not normalization, that's complicating your schema for the sake of implementation-dependent data optimization tradeoffs. And you should demonstrate this is needed and works.)

提交回复
热议问题