Still working on a web application as a school project, and it just seems to keep expanding.
I have to add a layer for teachers so they can manage and coach students through the application. So, I have to link teachers to their students.
I was wondering what the best way would be to do this. I have one table for all users at the moment. The bare basics of this table are:
id | email | firstname | lastname | role
1 | s#s.s | dromiceio | mimus | 1
2 | d#d.d | tyranno | saurus | 2
3 | a#a.a | utah | raptor | 1
Role is the number I assign to them to give them certain permissions. 1 = student, 2 = teacher, 3 = admin.
Assuming that one student has one teacher but one teacher has many students, what would be the best way to design my database table?
I was thinking of creating a new table and just putting the student/teacher ids in it:
For example, if teacher Tyranno Saurus (id 2) has the two students in the table above linked to him, I would make a table like this:
pk_id | teacherid | studentid
1 | 2 | 1
2 | 2 | 3
That way, I would know that teacher Tyranno (id 2) has two students, namely the student with userid 1 and userid 3.
Then again, I have never really worked on anything like this so I was wondering if anyone could give me some insight about this and if it's possible to do this in a better way.
I'm building my app in PHP (CodeIgniter) with MySQL; if that's of importance.
Thanks a lot.
If a student has zero-or-one teacher coaching them, then I would suggest adding a CoachID column to the student table that is a foreign-key to that particular teacher. The intermediate table you've suggested doesn't do anything to simplify this simple relationship, it actually makes it that little bit more complicated.
If you were tying students to classes (where each class has multiple students and each student takes multiple classes) then an intermediate many-to-many mapping table would be a must.
Related
the first is the sectors table that has an id and sector name like this
id | sector
1 | Government
2 | Education
The second is the employee table like this (simplified)
Id | name
1 | sam
2 | tom
Finally I have a sectorMap table (this is used to join the two tables above together) like this
Id | sectorid | employeeid
1 | 1 | 2
2 | 1 | 1
3 | 2 | 2
So in this instance, once I join everything together and view the sectors or each employee, it would show that tom has two sectors (government, education) and sam only has one (government)… hope that makes sense
My question is, within my application, the user has the ability to change these sectors by selecting from a multiple selection dropdown in html. For some reason I thought that by doing an update on duplicate expression would work, however seeing how I have multiple rows of data, I would need to delete all rows within the sectormap table that do not reflect the new selection and contain the selected employees id. What would be the best way of going about that?
For instance, in this case, lets say I open the application and see that tom has two sectors tied to him (government, education) and I only wanted him to have one (government). When I deselect education and select GO. The application returns a list to the server that contains (‘government’). How can I formulate an expression to delete the education sector row from the sectormap table that contains his id?
Your answer is in your question.
1st when you are deselecting education. You will get data of (‘government’). right?
So just invert your query. select those records which is not (‘government’), those are education.
So, education records are you can delete.
Hope this will help you. thanks:)
I have two table now:
conference table: id, name
people table: people_id, name
what I want to do
I want to make a new table so that I can get all attend people by conference id but also get all conference a specific man attended by people_id.
what I have thought
make a new table whose columns is all the people's id, and insert each conference as row, if the people shows in conference, we make it 1, otherwise 0. But it's too sparse and difficult to show which people attend a specific conference because we have many columns.
UPDATE
thanks for your comment. Now I create a table like this:
I think it's much better than the table before.
How about this?
A join table called conferences_people.
cp_id | conference_id | people_id
-------+---------------+-----------
1 | 1234 | 1
2 | 1234 | 4
3 | 1234 | 5
I have 3 tables called Teachers, Admin and Students and they all have an ID. How do I make it so that none of their IDs are the same.
As mentioned by #Ron in his comment, perhaps the easiest option here would be to just use a single users table with a role column, something like this:
id | role
1 | teacher
2 | student
3 | student
4 | admin
However, it is also fairly straightforward for you to continue using three separate tables for the teachers, students, and admins. You can logically make their IDs unique by just appending a prefix to each number, e.g. A123 is the 123rd admin, while S46 is the 46th student.
I have a large DB full or people called PERSONS.
I want to store their relationship to one another in a separate table.
I am thinking something like this:
FAMILY
PERSON_IDS: 123, 345, 678
RELATIONS: self, brother, daughter
Using a 'self' flag to indicate the person referring the relation-ship from. So, in the example 123 would be a man, 345 is his brother and 678 is a woman, his daughter. I.e, the gender information could be derived from the relationship.
Is this the right way to go about it?
Or would it be more efficient to have only 2 PERSONS per row and one relationship-type
PERSON_IDS: 123, 456
RELATION: brother
-
PERSON_IDS: 123, 678
RELATION: daughter
Or is it better to have a male/female field per person and the relation-ship table only specify eg "sibling".
Or should I have a table with PARENTS only and store the gender with the PERSON?
TABLE PARENTS:
PARENT_ID: 123
CHILD_ID: 678
The aim is to display related people when a Person is displayed. The design should be optimized for performance & speed rather than ease of administration.
Thanks for your help.
It's a many-to-many relationship: each person can have many relatives and also be a relative of many people. Assuming your Person table has a primary key named Id, you could have a table, which holds the relationship between two people as well as the kind of relationship they have. It would be useful to also have a table with all the possible kinds of relationships, something like this:
Relationship(Id, Kind)
Family(Person_Id, Relative_Id, Relationship_Id)
So if you have the following data for Person and Relationship tables:
Person: Relationship:
Id | Name Id | Kind
1 | John 1 | Father
2 | Mike 2 | Sister
3 | Susan
and the following for Family table:
P_Id | Rel_Id | Relation_Id
1 | 2 | 1
1 | 3 | 1
2 | 3 | 2
Family table is saying that John is the father of Mike and Susan, and that Mike's sister is Susan. I think this could be a good approach, but of course, as almost everything in databases design, this solution is arguable.
Imagine you live in very simplified example land - and imagine that you've got a table of people in your MySQL database:
create table person (
person_id int,
name text
)
select * from person;
+-------------------------------+
| person_id | name |
+-------------------------------+
| 1 | Alice |
| 2 | Bob |
| 3 | Carol |
+-------------------------------+
and these people need to collaborate/work together, so you've got a link table which links one person record to another:
create table person__person (
person__person_id int,
person_id int,
other_person_id int
)
This setup means that links between people are uni-directional - i.e. Alice can link to Bob, without Bob linking to Alice and, even worse, Alice can link to Bob and Bob can link to Alice at the same time, in two separate link records. As these links represent working relationships, in the real world they're all two-way mutual relationships. The following are all possible in this setup:
select * from person__person;
+---------------------+-----------+--------------------+
| person__person_id | person_id | other_person_id |
+---------------------+-----------+--------------------+
| 1 | 1 | 2 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
| 4 | 3 | 1 |
+---------------------+-----------+--------------------+
For example, with person__person_id = 4 above, when you view Carol's (person_id = 3) profile, you should see a relationship with Alice (person_id = 1) and when you view Alice's profile, you should see a relationship with Carol, even though the link goes the other way.
I realize that I can do union and distinct queries and whatnot to present the relationships as mutual in the UI, but is there a better way? I've got a feeling that there is a better way, one where this issue would neatly melt away by setting up the database properly, but I can't see it. Anyone got a better idea?
I'm not sure if there is a better way to configure your tables. I think the way you have them is proper and would be the way I would implement it.
Since your relationship table can indicate unidirectional relationships, I would suggest treating them as such. In other words, for every relationship, I would add two rows. If Alice is collaborating with Bob, the table ought to be as follows:
select * from person__person;
+---------------------+-----------+--------------------+
| person__person_id | person_id | other_person_id |
+---------------------+-----------+--------------------+
| 1 | 1 | 2 |
| 2 | 2 | 1 |
+---------------------+-----------+--------------------+
The reason is because in a lot of ActiveRecord (Rails) like systems, the many-to-many table object would not be smart enough to query both person_id and other_person_id. By keeping two rows, ActiveRecord like objects will work correctly.
What you should do is then enforce the integrity of your data at the code level. Everytime a relationship is established between two users, two records should be inserted. When a relationship is destroyed, both records should be deleted. Users should not be allowed to establish relationships with themselves.
There is no way I can see using simple relational concepts. You will have to add "business" code to enforce your person-person relationships.
One way might be to enforce a second relationship record using an insert trigger
then declare one of the records "primary" (e.g. the one where the person_id is smaller than the other _person_id)
then build views and glue code for your applications (select, update, delete) that access the data with this knowledge.
There is no better idea. Relational databases cannot enforce what you ask so you have to write a special query to retrieve data and a trigger to enforce the constraint.
To get the related persons for #person I would go for:
SELECT CASE person_id WHEN #person
THEN other_person_id
ELSE person_id
END as related_person_id
FROM person_person
WHERE ( person_id=#person
OR other_person_id=#person)
You should find this post useful:
http://discuss.joelonsoftware.com/default.asp?design.4.361252.31
As #user posted you are generally better off creating two records per bidirectional relationship (Alice to Bob and Bob to Alice in your example). It makes querying much
easier and it accurately reflects the relationships. If you do have true unidirectional relationships, it's the only way to fly.