简体   繁体   中英

“many to many to many” relation

I have a simple database of cosmetics. Each product may consist of multiple ingredients. Therefore it is a simple many to many relation and currently I have a database like this:

CREATE TABLE `products` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` TEXT NOT NULL,
  PRIMARY KEY (`id`),
);

CREATE TABLE `ingredients` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` TEXT NOT NULL,
  PRIMARY KEY (`id`),
);

CREATE TABLE `ingredient_to_product` (
  `ingredient_id` INT UNSIGNED NOT NULL,
  `product_id` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`ingredient_id`, `product_id`),
  INDEX (`product_id`)
);

However, some ingredients can have many different names. For example: "LINALOOL ESSENTIAL OIL", "LINALYL ALCOHOL" and "3,7-DIMETHYL-1,6-OCTADIEN-3-OL" refers to the same ingredient.

When I am presenting one product, I would like to keep ingredient name as on product label. So in case of one product it will be "LINALYL ALCOHOL" and in case of another product it may be something other, but referring to identical ingredient.

Now I would like to query database for all names of the product by specifying one of its names or by its ID, however how one ID could refer to many names? Do I have to keep two tables: one for specific ingredient in general and another table just for names (relation many names to one ingredient)? Is there any better way?

Ingredients

  • ID (int) (pkey) (ai)
  • Name (varchar)

Synonyms

  • ID (int) (pkey) (ai)
  • IngredientID (int) (foreign key maps to: Ingredients.ID )
  • Name (varchar)
  • Flag (optional; sample values: IUPAC Name , Common Name , Spanish Name , ...)

So yes, for the rules you described, you will at minimum have a primary name, and then a synonym table using the Ingredients.ID

I also introduced a Flag field so that you can programmatically choose when to use a synonym rather than just hard-coding it all the time. For example, if you're listing a product flagged as an industrial chemical , it would be programmed to pull the IUPAC * name

*IUPAC refers to conventions for naming chemicals, and is used by professional chemists almost always, but almost never used in consumer supermarkets: http://www.chem.uiuc.edu/GenChemReferences/nomenclature_rules.html

I suppose the good news is that one name cannot be used for multiple different ingredients, right?

So yes, you probably need an "ingredient name" table, something like

`name` TEXT NOT NULL,
`ingredient_id` INT UNSIGNED NOT NULL

(I'd probably just use name as the PK here, but if your design calls for always using surrogates then also add ingredient_name_id I guess...)

And then the details of the ingredient (except name) would still go in ingredient table. (You could keep a default name in the ingredient table as well, but I wouldn't. If you need that concept, I'd consider adding a "default flag" to the ingredient name table or something like that.)

Since you want to know the name used for each ingredient by a given product, you would replace your current "ingredient to product xref" with an "ingredient-name to product xref".

为什么不为其他成分名称/化学名称等创建单独的表,并将其与产品ID连接起来,以便在需要时可以单独使用,并避免在主表中包含任何NULL值。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM