0

I have a table materials which contains (I'm using web2py):

materials_db.define_table('materials',
    Field('name','string'),
    Field('reference','string'),
    Field('manufacturer','string'),
    Field('date_added','date'),
    Field('density','double'), # Density - kg/m³
    Field('emissivity','double'),
    Field('specific_heat','double'), # Specific Heat - kJ/kg.K
    Field('thermal_conductivity','double') # Thermal conductivity - W/m.K
    )

I now would like to create a table constructions. Each construction is an assembly of any number of materials in an ordered way, e.g. something like this:

+------------+-------+
|  Material  | Layer |
+------------+-------+
| Concrete   |     1 |
| Airgap     |     2 |
| Insulation |     3 |
| Plaster    |     4 |
+------------+-------+

Layer should enable changing the location of a material in the construction. Constructions will have new properties that will be calculated from the properties of the materials used and the location within the construction.

I don't really have a clue on how to go about it. The value for layer within a construction must be unique, however obviously must not be unique between constructions, i.e. every construction can have a layer with the value 1.

Do I need to create a new table for each construction and then reference all these table in my table constructions? That's the only vague idea I have at the moment, however that doesn't seem quite right... Is there a good way of doing this?

pandita
  • 4,739
  • 6
  • 29
  • 51
  • Just added a third secion to my answer re "properties that will be calculated". You *don't* want those in your database. Get them from queries. – philipxy Jun 15 '14 at 09:51

3 Answers3

1

You have two nouns: material and construction. Any material item may go into multiple constructions and any construction may consist of multiple materials. This is a classic many-to-many relationship. The nouns become entities which are kept in tables. A cross table defines the relationship:

create table MatConst(
  MatID int not null, -- Foreign key to Material table
  ConstID int not null, -- Foreign key to Construction table
  Qty number not null,  -- The number, volume or weight of Mat in Const.
  primary key( MatID, ConstID )
);

The two foreign keys become the primary key for the relationship table so for each thing being constructed, there can be only one entry for concrete, one for plaster and so on. The Qty field allows for amounts like 57 (pounds of concrete) or 150 (square feet of plaster). You may, of course, add other columns that describe the relationship as needed.

TommCatt
  • 5,498
  • 1
  • 13
  • 20
  • Thanks @TommCatt. If I understand correctly, I will end up with three tables: `materials` as above, `constructions` which will summarize and possibly process the information from the cross table `matconst`. Each row in `matconst` is primarily (MatID,ConstID), so when calculating the properties of a specific construction (e.g. overall thermal conductivity, price,...), it would parse the primary key in the `matconst` table to find rows which contain the ID of the construction I'm interested in. Did I understand this correctly? Sorry, I'm obviously a database noob.... – pandita Jun 15 '14 at 08:04
  • @pandita & TommCatt TommCatt has misread the question. The question's Material-Layer illustrated table is ordered layers of material for a given construction. pandita has a ternary relation with key (construction,level). Any other construction-material relationship is moot. Also pandita wants a base with derived info; it should have a view (or queries). – philipxy Jun 15 '14 at 11:42
  • @padita: Yes, you seem to have grasped the concept nicely. When ooking from a construction side, finding that ID on the ConstID field shows all the materials used in that construction. When looking from the material side, find the MatID of a particular material will find all the constructions which use that material. @philipxy: yes, I saw the `layer` attribute and did not immediately understand what it meant so I left that to others. It could be as simple as adding a `layer` field to MatConst becoming part of PK. Then could have layer of plaster, layer of insulation, layer of plaster, etc. – TommCatt Jun 16 '14 at 16:37
1

Write down statements you need to describe application situations.

Each statement gives a table. A table contains the rows that make its statement true.

materials(material_id,name,...) // material [material_id] has name [name] and ...
constructions(construction_id,purpose,...) // construction [construction_id] is good for [purpose] and ...
construction_layers(construction_id,material_id,layer) // construction [construction_id] layer [layer] is [material_id]

Constrain the database to states that can arise.

Only some application situations can arise. The statements plus those situations mean only some database states can arise. Tell the DMBS so it can stop other states. Say it in constraints.

Keys (PKs and UNIQUE column sets) say a base table's value is constrained. FKs express that tow tables are mutually constrained.

materials(material_id,name,...) // material [material_id] has name [name] and ...
    pk (material_id)
constructions(construction_id,purpose,...) // construction [construction_id] is good for [purpose] and ...
    pk (construction_id)
construction_layers(construction_id,material_id,layer) // construction [construction] layer [layer] is [material_id]
    pk (construction_id,layer)
    fk (construction_id) references constructions (construction_id)
    fk (material_id) references materials (material_id)

It would be nice if a DBMS would for each construction_layers row

CHECK(layer >= 1)

but that might or might not be possible without triggers with a particular DBMS.

We would also want to check that each construction's layers are contiguous (maybe not all the time). That you would have to do by triggers under current DBMSs.

Limit what you say in a statement in certain ways.

The only properties you should have in a base table other than its key columns are those that are a function of an entire key. (This gives a table in 5NF.) (A computed column is ok any time.)

Other information not derived from given base tables should be in a separate base table.

Any other table you want should be got as a query or view.

philipxy
  • 14,867
  • 6
  • 39
  • 83
1

I'm not familiar with web2py, but purely from the database perspective, your model should probably look like this:

enter image description here

  • Each construction has one row in CONSTRUCTION table.
  • Each material one row in MATERIAL table.
  • Each line in your BOM1 is one row in CONSTRUCTION_MATERIAL table and is identified through the composite key {CONSTRUCTION_ID, LAYER}.

In other words, this is a many-to-many relationship between constructions and materials, and the CONSTRUCTION_MATERIAL table acts as a "junction" or "link" table2. You can add fields such as "quantity" to the junction table, if necessary.


1 Bill or materials.

2 Albeit slightly "unusual": the MATERIAL_ID is not part of a key to allow the same material in different layers of the same construction. In contrast, if same material can appear only once per construction, just make another composite key: {CONSTRUCTION_ID, MATERIAL_ID}.

Community
  • 1
  • 1
Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
  • Like TommCatt you have misread the question. The question's Material-Layer illustrated table is ordered layers of material for a given construction. pandita has a ternary relation with key (construction,level). Any other construction-material relationship is moot. Also pandita wants a base with derived info; they should use a view (or queries). – philipxy Jun 15 '14 at 11:41
  • @philipxy In your comment above, did you intentionally use: "relation" and then "relationship", which are different terms? At any rate, a material will have the same density, thermal conductivity etc... independently from where it is used, so it has to be in its own table, no matter how you may later decide to proceed with representing the construction-material connections, or caching derived data or anything else... – Branko Dimitrijevic Jun 15 '14 at 11:47
  • 1. In the relational model a "relationship" is represented by a relation/table. Methods that don't understand it use "relationship" otherwise. So I try to use "statement" or "meaning" since "predicate" is too scary. Just read "table" for "relation" & "relationship". 2. Reread the question: the predicate/statement/meaning/relation/relationship is "CONSTRUCTIONS's level LEVEL is made of MATERIAL". Key (C,L), FKs (C),(M). I did not otherwise address other C or M or (explicitly) C-M tables/predicates. Except to say derived such is inappropriate to bases. – philipxy Jun 15 '14 at 12:32
  • @philipxy No, these are different terms. A [relation](http://en.wikipedia.org/wiki/Relation_(database)) is (represented at the physical level as) a table. RelationSHIP may be a foreign key or a junction table. The "relational model" is not called that way because tables may be connected via foreign keys, but because tables represent relations. Other than that, I don't really understand your points about the question or the answers - care to rephrase? – Branko Dimitrijevic Jun 15 '14 at 13:11
  • 1. I know the RM is called so because tables/relations represent relations. There are simply multiple uses of relationship & I used it as the name "Entity-Relationship" does. (Not as junction/association table per se but as the abstract thing that things are in when they are *in a relationship* or *related* in a specified way.) No more on this here. 2. I misread your C_M table. (Two columns in one row threw me.) Agree with your design. It is what I posted. "CONSTRUCTIONS's level LEVEL is made of MATERIAL" from my comment/answer is its characteristic predicate. – philipxy Jun 15 '14 at 14:02
  • @TommCatt, philipxy, Branko, thanks a lot guys! I learned a lot from your comments and answers. As with including calculated/derived values in the database itself: I might rethink this as I test my app. The reason why I wanted to include derived values is because the database will mainly be searched for constructions based on their derived properties (e.g. price, insulation value, etc.). I'll accept Branko's answer because I found the visual representation most useful. But thanks again to all of you. – pandita Jun 15 '14 at 20:26