Advice on building a database table - mysql

After doing some research I need some advice. This is a small project which allows teachers to post assignments online, and students to view/submit those assignments.
Students can have multiple courses assigned to them, so my question is: What is the best way to set up a table?
Example 1:
student courses
John Smith Math, Chemistry, English
Mary White Math, Biology
Example 2:
course students
Math John Smith, Mary White
Biology Mary White
Chemistry John Smith
English John Smith
I apologize in advance if this is a noobie question, but I want to avoid doing things wrong from the get-go and I'm open to any and all suggestions!
Thank you for your time.

It's generally not suitable to put more than one item in a column in a relational database. So create a table like this:
course student
Math John Smith
Math Mary White
Biology Mary White
Chemistry John Smith
English John Smith
Then, you can use this table in JOIN expressions to retrieve the info you want. You may want to have additional tables that describe the essential information about courses and students. Something like:
course instructor time
Math Albert Einstein 10:30
and
student id_number phone
John Smith 1234-5678 555-1212
...or whatever information you need to keep about courses and students.

Related

Primary Key and Functional Depe

I have a table below and I would like to get confirmation on one of the functional dependencies.
Taylor Johnson is the name of two twins who live in the same house.
Student ID is a unique ID and hence it is the candidate/primary key.
But Student ID doesn't functionally determine Student Name or does it? I don't think it does because knowing student ID wouldn't tell you which Taylor Johnson you are talking about. If that is the case, then I cannot say that my candidate/primary key (Student ID) functionally determines all other attributes in the table even though it is a unique key. Doesn't it then violate the definition of a primary key? Thanks for any insights in advance!
Student ID Student Name DOB Street City State Zip
1 Taylor Johnson 4/10/1988 Meadow Raleigh NC 27606
2 Taylor Johnson 4/10/1988 Meadow Raleigh NC 27606
3 Kim Blake 2/10/1998 Crescent Cary NC 27512

Show All Records For Given Field Filter In Access 2010 Table

Hopefully this will make sense...I have a table in Access 2010 that contains a list of suppliers and their point of contacts at the supplier and where I work. The POCs vary in number, anywhere from 1-4 up to this point. The table is set up so each POC is on a separate line.
The supplier could have one contact but work could have three different contacts and vice versa.
What I want to happen is when I select a value from a combobox on a form, all the related POCs need to be shown instead of cycling through them one by one.
For example, Supplier1 has two POCs at their facility and we have three at our facility. I would like to have the combobox find Supplier1 in the table and then show all the contacts for that supplier (their facility and ours) in a textbox.
The user will be able to edit the contact information and, if it is not too difficult, would be able to add/delete a contact.
I'm sure a question similar to this one has been asked before, however I have been unable to word it correctly to find a solution through google searches/this website. I'm comfortable enough with VBA to use that if required but am by no means an expert. I am completely unfamiliar with SQL and would like to avoid going that direction if at all possible.
I have to be careful with any data I provide but will do what I can if you need to see the data or anything like that.
Supplier Code Part Supplier Contact Procurement Contact QC Contact
Ajin AKVN Patrick Yong Jack
Ajin AKVN Chase Yong Jack
Autoliv AMNP Seatbelt Daryl James Lewis
Bosch AG48 Hancheul Kevin
Carlex AKJ5 QTR Glasses Bob Joy Zack
Continental ANKC Jacob
KSR C03A05 Brake Pedal Jose Paul David
KSR C03A05 Brake Pedal Jose Paul Gary
KSR C03A05 Brake Pedal Jose Paul Steven
KSR AG5Z Accelerator Pedal Jack Paul David
KSR AG5Z Accelerator Pedal Jack Paul Gary
KSR AG5Z Accelerator Pedal Jack Paul Steven
KSR AG5Z Accelerator Pedal Cory Paul David
KSR AG5Z Accelerator Pedal Cory Paul Gary
KSR AG5Z Accelerator Pedal Cory Paul Steven
Your table needs heavy normalization (see e.g. What is Normalisation (or Normalization)? or http://r937.com/relational.html )
I would suggest (Note: I'm not sure about the Supplier/Code/Part relation) :
- tSupplier
SupplierID SupplierName
1 Ajin
2 KSR
- tParts
PartID SupplierID Code Part
1 1 AKVN
2 2 C03A05 Brake Pedal
- tContactTypes
TypeID Type
1 Supplier
2 Procurement
3 QC
- tContacts
ContactID SupplierID TypeID ContactName
1 1 1 Patrick
2 1 1 Chase
3 1 2 Yong
4 1 3 Jack
and so on.
The first column of each table is the primary key, an autonumber field.
All other ID columns are foreign keys, linking to a parent table.
Now you can have a combobox for the Supplier, which gives the SupplierID.
With that, you can filter the Contacts and show them in a datasheet subform.
Either all in one table, with the ContactTypes as column, or in three subforms, each filtered by one ContactType.
To be able to add new contacts, use the BeforeInsert event to assign the current SupplierID.

Why this sentence in SQL is working? COUNT and WHERE to get Students from Teachers

I tried to create a VIEW that merge some tables in order to have the "hottest" teacher in a educational platform.
First, I have a table with the users (some teachers, some students),
then in other I have the lessons created by the teachers,
finally, other one that has the relation between students and lesson.
when I use this SQL sentence
CREATE OR REPLACE VIEW `skn_teachers` AS
select
`u`.`id_skn_users` AS `id_skn_users`,
`u`.`firstName` AS `firstName`,
`u`.`lastName` AS `lastName`,
COUNT(`ls`.`createdBy`) AS `countLessons`
from (`skn_users` AS `u`, `skn_rolesxusers` AS `rxu`, `skn_roles` AS `ro`, `skn_approved_lessons` AS `ls`)
where ((`rxu`.`id_skn_users` = `u`.`id_skn_users`) and (`rxu`.`id_skn_roles` = `ro`.`id_skn_roles`) and (`ro`.`name` = 'teacher') and (`ls`.`createdBy` = `rxu`.`id_skn_users`))
group by `u`.`id_skn_users`
the row countLessons show me the number of lessons per teacher eg.
id | firstName | lastName | countLessons
1 Pepito Perez 1
2 Julián Figueroa 7
3 Daniel Aguirre 2
which is correctly the number of lessons per teacher.
but I need the number of students that have the lessons created by each teacher (all of them, sum of all students in all lessons of THAT teacher), countStudentsByTeacher, in one of my attempts, get this SQl and it was a surprise when I got the number of students by teacher but I don't understand clearly what I did.
new SQL sentence:
CREATE OR REPLACE VIEW `skn_teachers` AS
select
`u`.`id_skn_users` AS `id_skn_users`,
`u`.`firstName` AS `firstName`,
`u`.`lastName` AS `lastName`,
COUNT(`ls`.`createdBy`) AS `countStudents`
from (`skn_users` AS `u`, `skn_rolesxusers` AS `rxu`, `skn_roles` AS `ro`, `skn_approved_lessons` AS `ls`, `skn_lessonsxusers` AS `lxu`)
where ((`rxu`.`id_skn_users` = `u`.`id_skn_users`) and (`rxu`.`id_skn_roles` = `ro`.`id_skn_roles`) and (`ro`.`name` = 'teacher') and (`ls`.`createdBy` = `rxu`.`id_skn_users`) and (`ls`.`id_skn_lessons` = `lxu`.`id_skn_lessons`))
group by `u`.`id_skn_users`
//
id | firstName | lastName | countLessons
1 Pepito Perez 10
2 Julián Figueroa 15
3 Daniel Aguirre 8
here, column countLessons shows really the number of students into all lessons created by each teacher, exactly what I wanted but I want to know why this works.
Thanks in advance!
In your 2nd query, you added at join to the table skn_lessonsxusers. This causes the 2nd query to return additional rows per each student that was assigned the lesson. The first query only returned the lessons that were created by each teacher.
Example:
Looking at the teacher "Daniel Aguirre", the underlying non-aggregated data for the first query might look like this:
id | firstName | lastName | Lesson
3 Daniel Aguirre Math 101
3 Daniel Aguirre CS 104
So there are 2 lessons that he teaches.
Now if you add in the students for each lesson, i.e. the 2nd query, then the data might look like this.
id | firstName | lastName | Lesson | Student
3 Daniel Aguirre Math 101 John
3 Daniel Aguirre Math 101 Bob
3 Daniel Aguirre Math 101 Sara
3 Daniel Aguirre Math 101 Mary
3 Daniel Aguirre CS 104 John
3 Daniel Aguirre CS 104 Bob
3 Daniel Aguirre CS 104 Dan
3 Daniel Aguirre CS 104 Sally
So now when you aggregate this 2nd set of data, it will show a count of 8 because there are 8 student/lesson combination for Daniel Aguirre.
Now assuming that John and Bob in the above 2nd data set are the same student, there are not really 8 different students taking lessons from Daniel Aguirre, there are 6 (John, Bob, Sara, Mary, Dan, and Sally). If you wanted to show 6 in this example you would use:
COUNT(DISTINCT `lxu`.`student_id`) AS `countStudents`
where student_id is the column that represents a unique student in the skn_lessonsxusers table. NOTE: your column is probably a different name than "student_id", but I don't know your table structure for this example so I just used "student_id".
It works because you multiply each lesson by each student in this lesson
join... 'skn_approved_lessons' AS 'ls'
where... and ('ls'.'createdBy' = 'rxu'.'id_skn_users')

How do I group by first name in MySQL?

I have a table where there is a full name column. I want to get either the unique given name or given names sorted by how many times they occur.
fullname
-----------
Barack Hussein Obama
Michael Jackson
William Jefferson Blythe
Michael Bloomberg
so the output will be either
Barack Hussein Obama
William Jefferson Blythe
Or
Barack Hussein Obama
William Jefferson Blythe
Michael Jackson
Michael Bloomberg
Or
1|Barack
1|William
2|Michael
Something like that. My aim is to see the foreign students in my database. I only have their full name to make a guess.
You can use SUBSTRING_INDEX(fullname,' ',1) to extract the "given name" as per your definition.
You can then use this for grouping or sorting as you seem fit, e.g.
SELECT COUNT(*),SUBSTRING_INDEX(fullname,' ',1) AS givenname
FROM yourtable
GROUP BY givenname;

how to design this database

I have a table for users. Each user has certain skills they teach. So for example:
Bob can teach karate
Louise can teach piano and knitting
Roger can teach judo, sailing and fencing
This is how I've done it in the database:
Table users
pk: uid, name
1 Bob,
2 Louise,
3 Roger
Table skills
pk: sk_id, skill
1 karate,
2 piano,
3 knitting,
4 judo,
5 sailing,
6 fencing
Table user_skill (relationship between user and skills)
pk:usk_id, fk:uid, sk_id
1 1 1,
2 2 2,
3 2 3,
4 3 4,
5 3 5,
6 3 6,
I want to then display "Roger has these skills: judo, basketweaving"
select name, skill
from users, skills, user_skill
where users.uid = user_skill.uid
and users.uid = 3
Is this the right way to go about it - both in terms of designing the tables and querying (mysql)?
Then say I want to update their profile with the areas they teach in:
Bob can teach karate in London
Louise can teach piano in Bolton and knitting in Manchester
Roger can teach judo in London and Manchester, sailing in Liverpool and fencing in Bradford
So I add the following tables:
Table cities
pk: city_id, city
1 London,
2 Manchester,
3 Liverpool,
4 Bolton,
5 Bradford,
But I'm confused as to how to do the relationships. I keep writing it out and realizing it doesnt work and starting again so I've obviously gone wrong somewhere.
I would say your general DB structure is fine as far as the relations go. To incorporate the cities aspect you could use your proposed cities table, but also add a column to your user_skill table to include a reference to the city table.
Also make sure you use proper join statements in the select queries as this is best practice and helps the queries run as efficiently as possible.
Can users teach skills in more than one location, e.g. "bob teaches judo in london and bolton"? Or is it strictly one skill-one city?
Depending on how you want your tables, you'd either just add a 'city' field to the user_skills table, and have multiple "bob/judo/cityX" "bob/judo/cityY" type records. Or you'll add yet another table "user_city_skills" where it'd be "user_skill_ID, cityID".
Your Structure looks fine except your usr_skill table. To incorporate the last part add a fk city_id in user_skill table. If the player can teach the same skill in multiple cities, you will need an additional table to avoid multi-valued columns.
Yes, carry on with it. You should also add one more column in table user_skill which will hold city_id.