I am having an argument with myself over the best way to do this.
Here is the scenario.
I have a table that has a list of users in it.
For simplicity let's say it looks like this:
Mike | male
Amy | female
Andy | male
and so on.
I then have a list of colours, let's say 4 colours:
red
blue
green
yellow
any of the users can have one or more of the colours assigned to them.
Do I add a new column to the users table called assignedColours, create a new table called colours that looks like this:
id | colour
1 | red
2 | blue
3 | green
4 | yellow
and then assign then store an array in the users assignedColours coloumn like
Mike | Male | 2,3
Amy | Female | 1,3,4
Or do I create a colour table with columns of the colours and assign the users to that column like:
Red | Blue | Green | Yellow
| Mike | Mike |
Amy | | Amy | Amy
or is there a better way of doing this all together?
I am looking for an answers as to which one is the preferred way and why.
Your first solution will give you problems if you need to search by colours.
Your second would give you extra work when adding more colours.
An additional table joining people & colours would be a good way to go. Check out information on Many-To-Many Relationships : http://www.singingeels.com/Articles/Understanding_SQL_Many_to_Many_Relationships.aspx.
You would want a UserColours table...as well as users & colours.
2 colums, UserId, ColourId
Primary key on UserId, ColourId so they do not have duplicates.
Why not creating an adjacency table? It will allow for easier joins and setting foreign keys.
Example:
Users
id| name | gender
-----------------
1 | Mike | male
2 | Amy | female
3 | Andy | male
Colors
id | name
1 | red
2 | blue
3 | green
4 | yellow
UserColors
user_id | color_id
1 | 3
1 | 2
2 | 1
4 | 2
The UserColors table allows you to associate the Users with the Colors.
The concept is known as adjacency table or join table and is used to map one2many and many2many relations.
You can find a more developed example here: http://www.joinfu.com/2005/12/managing-many-to-many-relationships-in-mysql-part-1/
Well, the idea behing RDS (Relational Data Store) such as MySQL, is to have the data normalized and thus, easily searchable.
Because of that, your best bet, is to save a table of colors, a table of users and a many-to-many table, saving the users-colors, their definition would be something along this line
users table
id | int
name | varchar
gender | varchar
colors table
id | int
name | varchar
users_colors table
id | int
user_id | int
color_id | int
this way, you can easily find all users having a certain color, whereas with an un-normalized scheme, you would run into a problem, how would you query for users with a certain color and not another?
Related
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.
MORE DETAILS:
Both of you recomend using JOIN. But the main problem is how to assign multiple SUBJECTS PER EACH CLASS without using multiple duplicate values. I will have ~200 de classes, with ~30 subjects per class. That means if 2 classes share the same 20 subjects, i will have 40 rows, all with "class_id = 1" but with "subjects_Id =1, subjects_id=2, etc" Its not very ergonomic. Any other ideas? Thanks for your time!
So, I am here again asking for your time and help friends.
I have a database that its almost ok. But I am stuck at trying how to link multiple values from a table to on collumn on another.
Let me be more explicit.
I have this table:
CLASSES
id | class_name | Matters |
-----------------------------
1 | Class1 | 13.4.2013 |
2 | Class2 | 14.4.2013 |
And this table:
Subjects
mat_id | show title |
-----------------
1 | English |
2 | French |
Now the problem is this. Each CLASS (e.g. CLASS1) should be able to study more Subjects at once. For example, CLASS 1 should be linked with subject (mat_id) 1, 3, 5, 6.
How to do this without repeating myself, and optimize the database? I tought that I should do it like so, but its not convenient :
CREATE A NEW TABLE named
SUBJECTS_PER_CLASS
id | class_id | mat_id |
----------------------------
1 | 1 | 1 |
2 | 1 | 3 |
BUT then I dont know how to query it. Any ideas? Any help will be greatly appreciated!
THANKS!
SELECT
*
FROM
CLASSES
JOIN
SUBJECTS_PER_CLASS
ON
CLASSES.ID = SUBJECTS_PER_CLASS.class_id
JOIN
Subjects
ON
Subjects.id = SUBJECTS_PER_CLASS.mat_id
You can use join command.
Reference 1
Reference 2
I want to create a friends system (something like in facebook).
I want to save relationship data in MySql, but I do not know which way is better:
To save everysingle relationship as a single entry, such as:
id | people1 | people2
1 | john | maria
2 | john | fred
3 | maria | fred
(there i declare relationships between all of these 3 peoples)
To save everyone name and list his friends:
id | people | friends
1 | fred | mary, john
2 | mary | john, fred
3 | john | fred, mary
Or maybe there is better way?
No Dear,
you just need one single table for make friend relationship. structure is following i have used
id (primary key) | my_id( integer logged user id ) | friend_id ( integer user id of another user he will receive friend request from logged user)
like we have two users in our users table then we have two entries for both user to make relation with each other
id | name | age
1 | vipan | 12
2 | karan | 12
then entry should be
id | my_id | friend_id
1 1 2
2 2 1
Please don't vote down in any case but i have use this table structure in my site and this is same structure used in joomsocial this is best table structure i think so i use it and please don't use comma separated values in table they will make problem in joins and relationship in some cases
Please see 4 number comment in this following link of post
Separate comma separated values from mysql table
The first one is the best no doubt cause the second one would not respect the first normal form.
You have to avoid multiple values in the same column cause it will get really painful to edit
Here's the link about database normalization. Most of the time, we respect the third normal form cause it's a good compromise between normalization and performance.
Also, like Randy said, you have to use the IDs so then you can link them with a foreign key.
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.
Is there a way to have "pointers to rows" in a database?
for example I have X product rows, all these rows represent distinct products but many have the same field values except their "id" and "color_id" are different.
I thought of just duplicating the rows but this could be error prone, plus making a small change would have to be done on several rows, again buggy.
Question: Is there a way to fill some rows fully, then use a special value to "point to" certain field values?
For example:
id | field1 | field2 | field3 | color_id
-----------------------------------------------
1 | value1 | value2 | value3 | blue
2 | point[1] | point[1] | point[1] | red (same as row 1, except id and color)
3 | point[1] | point[1] | point[1] | green (same as row 1, except id and color)
4 | valueA | valueB | valueC | orange
5 | point[4] | point[4] | point[4] | brown (same as row 4, except id and color)
6 | valueX | valueY | valueZ | pink
7 | point[6] | point[6] | point[6] | yellow (same as row 6, except id and color)
I'm using MySQL, but this is more of a general question. Also if this is goes completely against database theory, some explanation of why this is bad would be appreciated.
This does go against database design. Look for descriptions of normalization and relational algebra. It is bad mainly because of the comment you have made "duplicating the rows but this could be error prone, plus making a small change would have to be done on several rows, again buggy."
The idea of relational databases is to act on sets of data and find things by matching on primary and foreign keys and absolutely not to use or think of pointers at all.
If you have common data for each product, then create a product table
create table product (
product_id int,
field1 ...,
field2 ...,
field3
)
with primary key on product_id
The main table would have fields id, color_id and product_id
if product table looks like
product_id | field1 | field2 | field3
-----------------------------------------------
1 | value1 | value2 | value3
2 | valueA | valueB | valueC
3 | valueX | valueY | valueZ
The main table would look like
id | product_id | color_id
--------------------------------
1 | 1 | blue
2 | 1 | red
3 | 1 | green
4 | 2 | orange
5 | 2 | brown
6 | 3 | pink
7 | 3 | yellow
Sure there is a way to have pointers to rows in a database. Just don't use a relational DBMS. In the 1960s and 1970s, there were several very successful DBMS products that were based entirely on linking records together by embedding pointers to records inside other records. Perhaps the most well known of these was IMS.
The down side of having pointers to records in other records was that the resulting database was far less flexible than relational databases ended up being. For predeterimned access paths, a database built on a network of pointers is actually faster than a relational database. But when you want to combine the data in multiple ways, the lack of flexibility will kill you.
That is why relational DBMSes took over the field in the 1980s and 1990s, although hierarchical and network databases still survive for fairly specialized work.
As others have suggested, you should learn normalization. When you do, you will learn how to decompose tables into smaller tables with fewer coulmns (fields) in each table. When you need to use the data in joined fashion, you can use a relational join to put the data back together. Relational joins can be almost as fast as navigating by pointers, especially if you have the right indexes built.
Normalization will help you avoid harmful redundancy, which is the problem you highlighted in your question.
One way of doing this is to separate the columns that seem to have repeated data and put that in a separate table. Give each of the rows in this new table a unique id. Add a column to the original table which contains the id in the new table. Then use a FOREIGN KEY relationship between the original table and the new table's id column.
well this would be called normalization under normal circumstances .. the whole point of it is to deal with that kinda scenarios .. so no it cant be done the way u want to do it.. u will need to normalize the data properly.
Create separate tables for the field1, field2 and field three values.
Put existing values there, and reference them by putting their id's into your current table.
If you're using common string values, it's good to store the strings in a separate table and refer to them with foreign keys. If you're storing anything like an integer, it wouldn't be worth it - the size of the pointer would be comparable to the size of the data itself.
It does go against database theory because you're throwing the relational part of databases out the window.
The way to do it is to make an ObjectID column that contains the key of the row you want to point to.
id | field1 | field2 | field3 | color_id | object_id |
------------------------------------------------------------
1 | value1 | value2 | value3 | blue
2 | null | null | null | red | 1 |
3 | null | null | null | green | 1 |
4 | valueA | valueB | valueC | orange
5 | null | null | null | brown | 4 |
6 | valueX | valueY | valueZ | pink
7 | null | null | null | yellow | 6 |
But remember: This is a bad idea. Don't do it. If you did want to do it, that would be how.
There are instances where it's required; but after dealing with a system that was pervasive in this, I'd always try to find another way, even if it means duplicating data and letting your business layer keep everything straight.
I work in a system where this was done throughout the system, and it's maddening when you have to recreate the functionality of relationships because someone wanted to be clever.
The way you would want to implement this in a database would be to create two tables:
object_id | field1 | field2 | field3
and
instance_id | object_id | colour
And then the rows of the second would point to the first, and you could generate the full table of data you want on the fly by
select t1.*, t2.colour from t1 join t2 on (t1.object_id=t2.object_id)
You should probably have two tables with a foreign key relationship.
Example
Products:
Id
field1
field2
field3
ProductColors:
Id
ProductId
Color