Best way to normalize this data - mysql

I have two tables, 'Product' and 'Product Packs'.
One product can appear in many product packs and a product pack can have many products (A many to many relationship).
I have also created a linking table to try and resolve this relationship but I am left with the following conundrum:
-------------------
| Linking table |
-------------------
| Prod_Id | PP_id |
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 1 | 6 |
| 1 | 7 |
| 2 | 5 |
| 2 | 7 |
| 2 | 8 |
| 2 | 10 |
| 2 | 4 |
Is this normal practice for database design? Could this be refined further?

You have a good starting point.
Taking it here you should consider, making the two fields of the table into a composite primay key. That would prevent duplicate records as noted by #musical_coder.
You might also consider adding an integer column that indicates the quantity of products in the package.
Finally, you might want to add some metadata columns such as CreatedWhen, CreatedBy, LastUpdatedWhen, and LastUpdatedBy. These tend to come in handy from time to time.

In my experience I would say that's no problem with this kind of relationship, but you need to be very careful when analysing data, but how you model is logical that a product is in a package and a package contains n products. So that's not bad.

Edit: This is an obsolete answer since the poster fixed his example data to not contain duplicate tuples anymore
From a database normalization perspective, this design is a bit tricky: If having two identical tuples in that table is supposed to have a meaning (e.g., a count), then this table has a multi-set semantics, which does not mix well with the relational model, since you don't have a key.
Having a table (Prod_ID, PP_Id, Count) with primary key (Prod_ID,PP_Id) is be a better (third normal form) design.
Edit:
So your table becomes
create table t (Prod_Id int, PP_Id int, Count int, primary key(Prod_Id,PP_Id));
insert into t values
(1,3,2),
(1,4,1),
(1,5,1),
(1,6,1),
(1,7,1),
(2,5,1),
(2,7,1),
(2,8,1),
(2,10,1),
(2,4,1);
select * from t;
Prod_Id PP_Id Count
---------- ---------- ----------
1 3 2
1 4 1
1 5 1
1 6 1
1 7 1
2 5 1
2 7 1
2 8 1
2 10 1
2 4 1

Related

Count rows referring to a particular row, multiple referencing tables in MySql?

My question is the following:
As asked in the question "How to count amount of rows referring to a particular row foreign key in MySql?", I want to count table references involving multiple tables referring to the table I'm interested about. However here we want the specific number of references per row for the resourced table.
In addition, what about the variant where the tables do reference eachother, but the foreign key does not exist?
Let's setup some minimal examples;
We have three tables, here called A, B, and C. B and C refer rows in A. I want to count the total amount of references for each row in A.
Contents of the first table (A), and expected query results in the column 'Count':;
+----+------------+-------+
| ID | Name | Count |
+----+------------+-------+
| 1 | First row | 0 |
| 2 | Second row | 5 |
| 3 | Third row | 2 |
| 4 | Fourth row | 1 |
+----+------------+-------+
Contents of the second table (B):
+----+------+
| ID | A_ID |
+----+------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
+----+------+
Contents of the third table (C):
+----+------+
| ID | A_ID |
+----+------+
| 1 | 2 |
| 2 | 2 |
| 3 | 3 |
| 4 | 3 |
| 5 | 4 |
+----+------+
Important restrictions for a solution
The solution should work with n tables, for reasonable values of n. The example has n=2.
The solution should not involve a subset of the product set of all the tables. As some rows from A may be referenced a bunch of times in all the other tables the size of the product set may well be stupidly large (e.g. 10*10*10*... becomes big quickly). E.g. it may not be O(q^n) where n is the number of tables and q is the amount of occurrences.
This is a partial solution, which I believe still suffers from performance problems related to condition [2]
I'm adding this as an answer as it may be useful for those working towards a better solution
Apply the following query. Extend as necessary with additional tables, adding additional lines to both the sum and the set of JOINs. This particular solution will work as long as you have less than about 90 tables. With more than that, you will have to run multiple queries like it and cache the results (for example by creating a column in the 'A' table), then sum all these later on.
SELECT
COUNT(DISTINCT B.ID) +
COUNT(DISTINCT C.ID) -- + .....
AS `Count`
FROM A
LEFT JOIN B ON A.ID = B.A_ID
LEFT JOIN C ON A.ID = C.A_ID
Unfortunately, if you have often referenced rows, the query will have a massive intermediate result, run out of memory, and thus never complete.

Difficulty in database design

I am experiencing difficulty in MySQL database design.
I have the following tables:
school_table
id | school_name
---------------------------
1 | success primary school
stage_table
id | stage_name
---------------------------
1 | nursery
2 | primary
3 | secondary
school_stage_table
id | school_id | stage_id
---------------------------
1 | 1 | 1
2 | 1 | 2
school_stage_table is a linking table. This is because there is many to many relationship between school and stage, that is a single school may have many stages, and the same stage may have many schools.
The problem comes here:
Each stage has different attributes, and therefore different attribute values for different schools.
How do I model this scenario in a database? Need your help.
As you previously said that you are having some issues that how to store different attributes of each stage of each schools.
Here you can take one table which will store all the attributes of each stage. You can use following table for storing attributes.
Table :
school_stage_attributes_table
id | school_stage_id | attributes_name | attributes_value
------------------------------------------------------------
1 | 1 | attrib_1 | value_1
2 | 1 | attrib_2 | value_2
One option here would be to create a stage_attribute table containing at least the following four columns:
stage_attribute
id | school_id | stage_id | attribute
Each record in this table would correspond to a single attribute for a single stage, e.g.
1 | 1 | 1 | 'nap time'
2 | 1 | 1 | 'breakfast'
3 | 1 | 3 | 'phys ed'
I suspect that some of the difficulty in your mind was with the possibility of adding attribute columns to the stage_table for each attribute. Of course, this is problematical because each stage could have different numbers or types of attributes, and it won't scale for many attributes. The option I gave above eliminates many of these problems by using an arbitrary number of records to store the stage attribute information.
You should use table school_stage_table for this different attribute values for different schools.
If You will use the same attributes schema for multiple schools, then there should be one more table called for example school_stage_options with fields
school_stage_options_id | stage_id | option1 | option2 ....
and later use school_stage_options_id in school_stage_table instead of using stage_id.

how can we add two field in same column in sql table?

i want to create a database that consists all products rating and notes purchase by user
suppose that i create a table name "Users_rating_product" that consists some column
user_id ->INT
company->Varchar
product1 -> 3 (rating of product out of 5)|(review of product)
product2-> 4(rating)|(some review)
i want to know how can i do it in mysql . i'm using phpmyadmin for database creation
table looks like
user_id | company |Ac | TV | fridge
1 | goderaj |3 ,take more power |4,less power |5,efficient
i want to know how can i do this so that both rating and notes for product display in same column
For this you'll need a separate table. Call it ProductRating. Put a unique key (ID) to the table and reference that key to your Users_rating_product table.
For example:
Users_rating_product:
user_id | company |Ac | TV | fridge
1 | goderaj |1 | 2 | 3
2 | somecomp |4 | 5 | 6
ProductRating
ID | Rating | Review
1 | 3 | Take more power
2 | 4 | less power
3 | 5 | efficient
4 | 5 | excellent
5 | 1 | awful
6 | 3 | average
There are many ways that you can achieve your functionality.
but this is not standard format to write queries.
you can have comma seperated column in your database like this
user_id | company |Ac_mapping_id
1 | goderaj |1,REview for Ac
for Seperate two values you can do like this
PARSENAME(REPLACE(String,',','.'),2) 'Name'
for Detail Reference for splitting two values you can refer :
click To refer
Better Way is to store Product description in different table.
You can easily write queries to retrieve your data
user_id | company |Ac_mapping_id | TV_mapping_id | fridge_mapping_id
1 | goderaj |1 | 2 | 3
& store all the ratings & reviews in mapping table like this
Ac_mapping_id | Rating |Review
1 | 1 |abcd
So on for the other table.
For Retrieving all the data just Use Left outer join
Select
*
from
Users_rating_product mm
Left outer join Ac_mapping_table ac on ac.ac_mapping_id = mm.ac_mapping_id
.....so on

How to store family tree data in a mysql database

I have a family tree. I would like to store it in a mysql database. I have a table with a column called "family members," but i don't know how to arrange these family members. For example, I am under my dad and my son is under me. So i guess, how can i store this type of tree in a database?
So, you said you have a table with a column called "family members". For me, that's just inappropriate because it doesn't respect normalization :) First of all I would call it "familyTreeId". Now, let's move to the FamilyTree table.
This table would be something like this:
FamilyTree(id, motherId, fatherId, etc) --> etc: if you have additional data
id will be the primary key of the table
motherId will link to the row in the FamilyTree table that belongs to the mother
fatherId will link to the row in the FamilyTree table that belongs to the father
So the rows will be:
+--------+--------------+--------------+
| id | motherId | fatherId |
+--------+--------------+--------------+
| son1 | yourwife | you |
| son2 | yourwife | you |
| you | mother | father |
| mother | grandmother1 | grandfather1 |
| father | grandmother2 | grandfather2 |
+--------+--------------+--------------+
Other option would be to store the couples
FamilyTreeParents(id, motherId, fatherId)
FamilyTreeNodes(id, familyTreeParentsId)
id will be the primary keys of the tables
familyTreeParentsId will be a foreign key to a FamilyTreeParents table
motherId will be a foreign key to a row in the FamilyTreeNodes table that belongs to the mother
fatherId will be a foreign key to a row in the FamilyTreeNodes table that belongs to the father
So the rows will be:
FamilyTreeParents
+----+--------------+--------------+
| id | motherId | fatherId |
+----+--------------+--------------+
| 1 | yourwife | you |
| 2 | mother | father |
| 3 | grandmother1 | grandfather1 |
| 4 | grandmother2 | grandfather2 |
+----+--------------+--------------+
FamilyTreeNodes
+--------+---------------------+
| id | familyTreeParentsId |
+--------+---------------------+
| son1 | 1 |
| son2 | 1 |
| you | 2 |
| mother | 3 |
| father | 4 |
+--------+---------------------+
Data is more normalized this way because you are not repeating information (like you and yourwife for son1 and son2 as I did in the other solution. However, this solution might be less efficient in terms of speed because there will be needed more joins.
I would keep two tables, one with persons, other with relations.
Question here is if you should keep the realtion in one record (eg husband - wife) or also from the other person's view (1:husband - wife, 2:wife - husband)
Advantage of second approach is quick searches so fast rendering of eg a layout but also larger table with more writes when data change and possible errors.
I would take the first approach and use some index to make the searches quicker.
So with a minimum of connections you could write out the following family
grandfather louis(id1)
x grandmother clothild(id2)
father francois(id3)
x mother diana(id4)
me peter(id5)
x my first wife fabienne(id6)
my son laurent(id9)
x my second wife jane(id7)
my son tristan(id10)
my brother hans(id8)
as
1x2
3x4
5x6
5x7
1>3
2>3
3>5
4>5
3>8
4>8
6>9
5>9
5>10
7>10
or shorter
1x2>3
3x4>5
3x4>8
5x6>9
5x7>10
So in a databasetable this gives
id_partner1 id_partner2 id_child
1 2 3
3 4 5
3 4 8
5 6 9
5 7 10
You can have schema like this
Family( Parent_name, Child_name ). The "tuple" (Parent_name, Child_name) are the key of your table. Assuming there is no duplicate (Parent_name, Child_name) exist in your family tree. If you have anything like Social Security Number to uniquely identify a person in the family tree, then you should the Parent_ssn, Child_ssn instead of names and have a separate table to store the relation between ssn and name, whose key would be ssn
items in this table can be
[Your dad, you]
[Your mum, you]
[you, your son]
[you, your 2nd son]
[your wife, your son]
Hope this helps
The schema can be this:
id
person
related_person
relation
comments
1
Mac
Mac's Brother
Brother-Brother
2
Mac' mother
Mac
Mother-Son
3
Mac
Mac' mother
Son-Mother
actually same as 2
Support more relationships, even ex-wife and ex-husband.
Also cost-saving, only one row is required between any two people, because their relationship can be reversed.
MARK: It is feasible for a small amount of data.

HTML listing of recordset, resulting from a join on two tables that relate one-many

I have two tables, that relate via a one-to-many relationship i.e
tableOne (1)----------(*) tableTwo
Given the basic schema below
tableOne {
groupID int PK,
groupTitle varchar
}
and
tableTwo {
bidID int PK,
groupID int FK
}
Consider the two tables yield the following record-set based on joining the tables on the tableOne.groupID = tableTwo.groupID,
tableOne.groupID | tableOne.groupTitle | tableTwo.bidID | tableTwo.groupID
________________________________________________________________________________
1 | Physics Group | 1 | 1
2 | Chemistry Group | 2 | 2
2 | Chemistry Group | 3 | 2
1 | Physics Group | 4 | 1
I would like to list such a record-set in an HTML table as follows:
tableOne.groupID | tableOne.groupTitle | tableTwo.bidID | tableTwo.groupID
________________________________________________________________________________
1 | Physics Group | 1 | 1
| Physics Group | 4 | 1
2 | Chemistry Group | 2 | 2
| Chemistry Group | 3 | 2
I'm interested in finding out if this can be done in SQL, or alternatively finding out ways of listing such a record-set in HTML using good standards.
The solution that comes to mind is simply iterating through the record-set and leveraging a sentinel to list all records with the same tableOne.groupID grouped in a single row <tr> - and also listing tableOne.groupIDs once as a unique identifier of that record-group. However I don't want to go down that path as I would like to avoid mixing code with HTML if possible.
You can order the sql results using the ORDER BY clause.
So if you add
ORDER BY tableOne.groupID ASC, tableTwo.bidID ASC
in your query, you are half-way there.
Next step is to loop and print the recordset from your asp page, but also check if the last groupID is different than the current, in order to decide whether to show it or not..