I am designing a database to organize materials for 3D production.
Materials are named like 1_Fabric_01_Textile_001_BlueJeans_Denim and 2_Metal_02_BrushedMetal_002_ChromeBrushed_Chrome, etc
So, I need a materials table, which basically has information on material name (last value, look above) and a combination of type and subvariant. Each type has allowed variants like 1_Fabric has 01_Textile, 02_Leather, 2_Metal has 01_Metal, 02_BrushedMetal and so on.
Now making all combinations would not be difficult (i.e., being able to choose every possible subvariant for every material type), but I want to limit the combinations to only allowed combinations, so users cannot choose invalid combinations (like 1_Fabric_01Metal or 2_Metal_01Textile).
Any ideas?
In order to generate those kind of name
1_Fabric_01_Textile
2_Metal_02_BrushedMetal
Based on the followin tables
Type
----------
Id Name
-- ------
1 1_Fabric
2 2_Metal
SubType
------------
Id Name
-- ------
1 01_Textile
2 02_Leather
3 01_Metal
4 02_BrushedMetal
And keeping rules on what types can relate to subtypes
You ill need a relational table like:
Type_SubType
-----------------
TypeId SubTypeId
------ ---------
1 1
1 2
2 3
2 4
and if you need more levels of subtypes you can add more tables
1_Fabric_01_Textile_001_BlueJeans_Denim
2_Metal_02_BrushedMetal_002_ChromeBrushed_Chrome
SubSubType
--------------
Id Name
-- ----------
1 001_BlueJeans_Denim
2 002_ChromeBrushed_Chrome
Type_SubType_SubSubType
-------------------------
TypeId SubTypeId SubSubType
------ --------- ----------
1 1 1
2 3 2
Now the trick part is to do a better normalization for the third level relation. It can be achieved if you add a identity column to the first relational table
So instead you can use this example:
Type_SubType
---------------------
Id TypeId SubTypeId
-- ------ ---------
1 1 1
2 1 2
3 2 3
4 2 4
and relating it to the second relational table
Type_SubType_SubSubType
-------------------------
Type_SubTypeId SubSubType
-------------- ----------
1 1
3 2
to retrieve only the possible matches is trivial
select * from type tp
join Type_SubType tp_sb on tp_sb.TypeId = tp.Id
join SubType sb on sb.Id = yb_sb.SubTypeId
or just (if you already selected a type and put it in the variable #TypeId)
Select * from SubType sb
join Type_SubType tp_sb on tp_sb.SubTypeId = sb.Id
where tp_sb.TypeId = #TypeId
and so on for SubSubTypes
note: this solutions only covers a fixed (or maxed) number of sub-sub. To get a total dynamic level of abstractions you ill need a recursive FK. Not something like rocket science but if you still the basics on SQL try stick with the most simple example.
Related
This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 2 years ago.
Hello to Folks out there,
I need some suggestion on How to design MySQL Table Structure for search optimization.
I am creating a Real estate website. In that I have property table and all its associated tables.
I can design my table for saving these records in two ways.
I have amenity master table
id property_name
----------------
1 Property A
2 Property B
3 Property C
Approach 1
Property Table
id property_name
----------------
1 Property A
2 Property B
3 Property C
Property_Amenities table
id p_id amenity_id
------------------------
1 1 1
2 1 2
3 1 3
4 1 4
5 2 1
6 2 1
Approach 2
Property Table
id property_name amenity_id
----------------------------
1 Property A 1,2,3,4,5
2 Property B 1,4,7,9,12
3 Property C 3,4,7,8,9,10
Approach 1 Query : I can join tables and get the all the amenities name for a particular property. Add the required index for optimization. For A property there will be 20 amenities on averages. Suppose I have 100K property records then to get amenities for particular property, MySQL query will search in 2 millions records of Property_Amenities table.
Approach 2 Query : I can search using FIND_IN_SET or IN MySQL operator. But I was going through this search topic and it seems that this approach will be much resource intensive and cost more for same amount of data i.e 100k property records.
Any suggestion will be appropriated. What your thought on this scenario or any other approach I should follow.
Use the first approach. Period. The second is wrong, wrong, wrong. Here are some reasons:
A SQL string should not be used to store multiple values.
Integers should be stored using the proper type.
Foreign key relationships should be declared.
SQL has very poor string handling methods.
SQL has a great way to store lists; it is called a "table" not a "string".
This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 3 years ago.
This is the table of database
**
id products free_pro_id
1 laptop 2
2 pen-drive -
3 hard-disk 2,4
4 mouse 3
i am just wondering how to create query for below output
product free_id_pro**
laptop pen-drive
hard-disk pen-drive,mouse
mouse hard-disk
I understand your problem. But your table implementation is not correct.
First, you have to learn about Database Normalization.
Please refer to this link
https://www.studytonight.com/dbms/database-normalization.php
You can have a table for products and another table for promotions.
Table Products
In this table you can have the prodId and the prodName
prodId-------prodName
1--------------laptop
2--------------pen_drive
3--------------hard_disk
4--------------mouse
Table Promotion
In this table, you can store what are the free products you are giving when user buys a product.
promoId--prodId----freeProdId
1-------------1------------2
2-------------3------------2
3-------------3------------4
4-------------4------------3
If you want to get the free products given for laptop you can do the following query
SELECT freeProdId from Promotion where prodId = 1;
I have given a very simple query to give you a basic understanding. You can modify the query, play around with it and do many things. (Ex. Get the prodName instead of the id)
This is the table of database arrange this type of product table in database
id ----- products ----- free_pro_id
1 ------- laptop --------- 2
2 ------- pen-drive-------- -
3 ------ hard-disk ------- 2
3 ------ hard-disk ------- 4
4 ------- mouse ---------- 3
This is the query to get output of above table
SELECT foo.products ,product.products FROM product foo inner join product on foo.id=product.free_pro_id
I have a table in Mysql that looks like this:
Name Slot_1 Slot_2 Slot_3
------ ------ ------ --------
MyName MyItem
MyName2
And I have this app with an interface to buy some products. When the client "MyName" buy something in the app, it would store it on "Slot_2" because "Slot_1" is already used; On the other hand, if MyName2 buys the same product, it would be stored on Slot_1 because it's the first free slot found. I searched through several links, but all I found was how to update the first empty row found, and not the column.
Note: The app is made in VB.net, so if you think it would be better to do this app-level, feel free to comment.
Note 2: This is the best db-design I found to do this "inventory". If you think there is a better way to do it, please point me to it.
That is really a bad design. I really suggest to read something basic on building relational databases.
Said that the only correct approach is to have at least three tables
The first table contains the customer informations
IDCustomer Name Address City
---------- ------ ------ --------
1 Steve XXXX YYYY
2 Andre KKKK ZZZZ
The second table contains the Items that can be sold
IDItem Item Price
---------- ------ ------
1 Apple 1
2 Orange 2
The third table links the Customers with the Items sold
IDItem IDCustomer Quantity
------- ----------- ---------
1 1 5
2 2 10
1 2 3
Also if you want to limit the items sold to a customer to only three, that is a business rule that should not be enforced by a database design like that.
Supoose I have the following:
tbl_options
===========
id name
1 experience
2 languages
3 hourly_rate
tbl_option_attributes
=====================
id option_id name value
1 1 beginner 1
2 1 advanced 2
3 2 english 1
4 2 french 2
5 2 spanish 3
6 3 £10 p/h 10
7 3 £20 p/h 20
tbl_user_options
================
user_id option_id value
1 1 2
1 2 1
1 2 2
1 2 3
1 3 20
In the above example tbl_user_options stores option data for the user. We can store multiple entries for some options.
Now I wish to extend this, i.e. for "languages" I want the user to be able to specify their proficiency in a language (basic/intermediate/advanced). There will also be other fields that will have extended attributes.
So my question is, can these extended attributes be stored in the same table (tbl_user_options) or do I need to create more tables? Obviously if I put in a field "language_proficiency" it won't apply to the other fields. But this way I only have one user options table to manage. What do you think?
EDIT: This is what I propose
tbl_user_options
================
user_id option_id value lang_prof
1 1 2 null
1 2 1 2
1 2 2 3
1 2 3 3
1 3 20 null
My gut instinct would be to split the User/Language/Proficiency relationship out into its own tables. Even if you kept it in the same table with your other options, you'd need to write special code to handle the language case, so you might as well use a new table structure.
Unless your data model is in constant flux, I would rather have tbl_languages and tabl_user_languages tables to store those types of data:
tbl_languages
================
lang_id name
1 English
2 French
3 Spanish
tbl_user_languages
================
user_id lang_id proficiency hourly_rate
1 1 1 20
1 2 2 10
2 2 1 15
2 2 3 20
3 3 2 10
Designing a system that is "too generic" is a Turing tarpit trap for a relational SQL database. A document-based database is better suited to arbitrary key-value stores.
Excepting certain optimisations, your database model should match your domain model as closely as possible to minimise the object-relational impedance mismatch.
This design lets you display a sensible table of user language proficiencies and hourly rates with only two inner joins:
SELECT
ul.user_id,
u.name,
l.name,
ul.proficiency,
ul.hourly_rate
FROM tbl_user_languages ul
INNER JOIN tbl_languages l
ON l.lang_id = ul.lang_id
INNER JOIN tbl_users u
ON u.user_id = ul.user_id
ORDER BY
l.name, u.hour
Optionally you can split out a list of language proficiencies into a tbl_profiencies table, where 1 == Beginner, 2 == Advanced, 3 == Expert and join it onto tbl_user_languages.
i'm thinking it's a mistake to put "languages" as an option. while reading your text it seems to me that english is an option, and it might have an attribute from option_attributes.
I have a table User that stores user information - such as name, date of birth, locations, etc.
I have also created a link table called User_Options - for the purpose of storing multi-value attributes - this basically stores the checkbox selections.
I have a front-end form for the user to fill in and create their user profile. Here are the tables I have created to generate the checkbox options:
Table User_Attributes
=====================
id attribute_name
---------------------
1 Hobbies
2 Music
Table User_Attribute_Options
======================================
id user_attribute_id option_name
--------------------------------------
1 1 Reading
2 1 Sports
3 1 Travelling
4 2 Rock
5 2 Pop
6 2 Dance
So, on the front-end form there are two sets of checkbox options - one set for Hobbies and one set for Music.
And here are the User tables:
Table User
========================
id name age
------------------------
1 John 25
2 Mark 32
Table User_Options
==================================================
id user_id user_attribute_id value
--------------------------------------------------
1 1 1 1
2 1 1 2
3 1 2 4
4 1 2 5
5 2 1 2
6 2 2 4
(in the above table 'user_attribute_id' is the ID of the parent attribute and 'value' is the ID of the attribute option).
So I'm not sure that I've done all this correctly, or efficiently. I know there is a method of storing hierarchical data in the same table but I prefer to keep things separate.
My main concern is with the User_Options table - the idea behind this is that there only needs to be one link table that stores multi-value attributes, rather than have a table for each and every multi-value attribute.
The only thing I can see that I'd change is that in the association table, User_Options, you have an id that doesn't seem to serve a purpose. The primary key for that table would be all three columns, and I don't think you'd be referring to the options a user has by an id--you'd be getting them by user_id/user_attribute_id. For example, give me all the user options where user is 1 and user attribute id is 2. Having those records uniquely keyed with an additional field seems extraneous.
I think otherwise the general shape of the tables and their relationships looks right to me.
There's nothing wrong with how you've done it.
It's possible to make things more extensible at the price of more linked table references (and in the composition of your queries). It's also possible to make things flatter, and less extensible and flexible, but your queries will be faster.
But, as is usually the case, there's more than one way to do it.