How to model "participation in container and child" - mysql

Considering this ER diagram
we have Students who are admitted to participate in an Exam, and each Exam can be split up into multiple Runs (for example, to split up large groups across multiple rooms or to have two Runs for the same Exam in direct succession).
Is it possible to ensure (via database constraints) that Students participate only in Runs that belong to Exams they are admitted to?
I couldn't find a way on my own and also don't know how to phrase this for an internet search.

You have these tables and columns:
exam: id, name
student: id, name
run: id, exam_id (foreign key to exam.id), when (timestamp), room
You need a new intersection table to keep track of what exam is being taken by which student:
int_exam_to_student: exam_id, student_id - both foreign keys
Now, you can query this to determine what runs a student is allowed to be in:
select run.* from run join int_exam_to_student i on (run.exam_id = i.exam_id) where i.student_id = 123;

Related

mySQL: how to go along 3 different tables, referring to different column in each table but using primary keys

I'm trying to find out which schools had students that did not complete their exams in 2018. So I've got 3 tables set up being: ExamInfo, ExamEntry and Students. I'm going to try use the ExamInfo table to get information from the Students table though, I obviously only want the student information that did not complete their exam in 2018. Note: I'm looking for students that attended, though did not complete the exam, with this particular exam you can look at completed exam as passed exam.
Within ExamInfo I have the columns:
ExamInfo_Date --when exam took place, using to get year() condition
ExamInfo_ExamNo --unique student exam ID used to connect with other tables
ExamInfo_Completed --1 if completed, 0 if not.
...
Within ExamEntry I have the related columns:
ExamEntry_ExamNo --connected to ExamInfo table
ExamEntry_StudentId --unique studentId used to connect to Students table
ExamEntry_Date -- this is same as ExamInfo_Date if any relevance.
...
Within Students I have following columns:
Students_Id --this is related to ExamEntry_StudentId, PRIMARY KEY
Students_School --this is the school of which I wish to be my output.
...
I want my output to simply be a list of all schools that had students that did not complete their exams in 2018. Though my issue is with getting from the ExamInfo table, to finding the schools of which students did not complete their exam.
So far I've:
SELECT a.Students_School, YEAR(l.ExamInfo_Date), l.ExamInfo_Completed
FROM ExamInfo l ??JOIN?? Students a
WHERE YEAR(l.ExamInfo_Date) = 2018
AND l.ExamInfo_Completed = 0
;
I'm not even sure if going through the ExamEntry table is necessary. I'm sure I'm meant to use a join, though unsure of how to appropriately use it. Also, with my 3 different SELECT columns, I only wish for Students_School column to be output:
Students_School
---------------
Applederry
Barnet Boys
...
Clearly, you need a JOIN -- two in fact. Your table has exams, students, and a junction/association table that represents the many-to-many relationship between these entities.
So, I would expect the FROM clause to look like:
FROM ExamInfo e JOIN
ExamEntry ee
ON ee.ExamEntry_ExamNo = e.ExamNo JOIN
Students s
ON ee.ExamEntry_StudentId = s.Students_Id

Get stats table from a many to many relationship

I have a pivot table for a Many to Many relationship between users and collected_guitars. As you can see a "collected_guitar" is an item that references some data in foreign tables (guitar_models, finish).
My users also have some foreign data in foreign tables (hand_types and genders)
I want to get a derived table that lists data if I look for a particular model_id in "collected_guitar_user"
Let's say "Fender Stratocaster" is model id = 200, where the make is Fender (id = 1 of makes table).
The same guitar could come in a variety of finish hence the use of another table collected_guitars.
One user could have this item in his collection
Now what I want to find by looking at model_id (in this case 200) in the pivot table "collected_guitar_user" is the number of Fender Stratocasters that are collected by users that share the same genders.sex and hand_types.type as the logged in user and to see what finish they divide in (some percent of finish A and B etc...).
So a user could see that is interested in what others are buying could see some statistics for the model.
What query can derive this kind of table??
You can do aggregate counts by using the GROUP BY syntax, and CROSS JOIN to compute a percentage of the total:
SELECT make.make, models.model_name as model, finish.finish,
COUNT(1) AS number_of_users,
(COUNT(1) / u.total * 100) AS percent_owned
FROM owned_guitar, owned_guitar_users, users, models, make, finish
CROSS JOIN (SELECT COUNT(1) AS total FROM users) u
WHERE users.id = owned_guitar_users.user_id
AND owned_guitar_user.owned_guitar_id = owned_guitar.id
AND owned_guitar.model_id = models.id
AND owned_guitar.make_id = make.id
AND owned_guitar.finish_id = finish.id
GROUP BY owned_guitar.id
Please note though, that in cases where a user owns more than one guitar, the percentages will no longer necessarily sum to unity (for example, Jack and John could both own all five guitars, so each of them owns "100%" of the guitars).
I'm also a little confused by your database design. Why do you have a finish_id and make_id associated directly in the owned_guitar table as well as in the models table?

MySQL Attendance System , Problems with joining tables, duplicate id's for 1 primary key

Ok So I am creating a Attendance System for a College and I am having trouble doing the tables in MySQL
The Problem I'm having is Grouping a group of students together for one class. So in MySQL
TABLE NAME: CourseGroup: courseGroup_id , student_id(FK), course_id(FK)
I want a number of students belonging to one class, this in hindsight will enable a teacher to undertake a register for that class group
In MySQL I have set the 'courseGroup_id as a unique field, however when I try to link 'courseGroup_id' in the Attendance table it only enables me to select 'student_id' and 'course_id'
Is it possible to select the courseGroup_id and display students for one class
My Attendance table looks like this:
Attendance: week_number, day, time, courseGroup_id, present
I want to be able to view all the students that belong to one class
I’m a bit lost with your terminology, you speak of “class id” but don’t reefer to that in your question – instead you use “course”.
I think the best option you can do here is create another table enabling a many to many relationship as many students can be registered to one or many courses. This type of table will enable a mapping between students and courses.
For example, if you create the mapping table “student_courses” with
student_id INT
course_id INT
You can then select students by course (joining the student table)
SELECT * from student_courses sc
INNER JOIN students s
ON s.student_id = sc.srudent_id
WHERE sc.course_id = ?CourseId
You can also reverse it and show the courses by for an individual course:
SELECT * from student_courses sc
INNER JOIN courses cs
ON cs.courset _id = sc.course_id
WHERE sc.student_id = ?StudentId
It is also worth pointing out that there should be two index on the student_courses, indexing both student_id and course_id for performance reasons.

Transition (many to many join) tables in MySQL; allowing for duplicate entries to link 1 column to multiple other columns in different table

Ok, so I am going to try and be specific as possible but my MySQL skills are pretty weak. So here is the situation:
I have 2 tables: Donor and Students. A donor can be linked to as many students as they want and each student can be linked to as many donors as donors want to "claim" them. So if I have Sally, a student, she can have Jim, a donor, and Jeff, a donor, be linked to her. So, I have all my students in one table and all my donors in another table. I need to put them together show the students name, id and the id of all the donors that the student is linked to.
Currently my tables are: Donor with DonorID, FirstName, LastName, DonorType, StreetAddress, etc. Then Students with: StudentID, FirstName, LastName and DonorID. However, that only allows me to link a student with one donor. So, I was thinking I need to make a transition table that would allow me to show the StudentID, FirstName(of student), LastName(of student), and the DonorID that "claims" that student and allow for me to duplicate StudentID and put a different DonorID in the 2nd, 3rd, 4th, so on and so on entries of the same student.
So, I guess my question is how do transition tables work in MySQL; I believe I am going to need to work with the JOIN function and join the two tables together but after reading about that on tizag.com I am even more confused. I have worked with Access where when you create a transition table you can pull the PK from each table and create a composite key using the two keys from the other tables but I am not quite sure how to do that in MySQL; does it work essentially the same and I should be pulling the PK from each table and linking them together in the 3rd, transition, table?
Marvin's right.
You need three tables to pull this off.
Donor
DonorID
FirstName
LastName
DonorType
StreetAddress
etc.
Student
StudentID
FirstName
LastName
etc.
Then you need Student_Donor. This is often called a join table, and implements the many-to-many relationship.
StudentID (PK) (FK to Student)
DonorID (PK) (FK to Donor)
DonorOrdinal
If StudentID = 5 has four donors with ID = 6,7,11,15, then you'l have these rows
StudentId DonorId DonorOrdinal
5 6 1
5 7 2
5 11 3
5 15 4
The DonorOrdinal column allows you to specify a student's primary donor and secondary donors. I can't tell from your question how important that is, but it's helpful to be able to order these things. Remember this: formally speaking, a SQL SELECT query returns rows in an unpredictable order unless you also specify ORDER BY.
If you want to display your students and their donors, you'll need this query:
SELECT s.StudentID, s.FirstName, s.LastName,
sd.DonorOrdinal,
d.DonorType, d.DonorID, d.FirstName, d.LastName
FROM student s
LEFT JOIN student_donor sd ON s.StudentID = sd.StudentID
LEFT JOIN donor d ON sd.DonorID = d.DonorID
ORDER BY s.StudentID, sd.DonorOrdinal, d.DonorID
This will show you all students (whether having donors or not per LEFT JOIN) in order of ID, then their donors in order of DonorOrdinal.
Yes, pretty much. What you are talking about is a Many to Many relationship. Your donor table should not include a reference to the student table (and vice versa). You'll need a new table (what you are calling a transition table) that contains the DonorId and StudentId. This can comprise your primary key or you can use another column for the primary key that is an auto_increment.

Database: Tables design/structure

I am new to database structure and design. Currently, I am in the process of creating a course catalog that will match course description according to course name and date. I have sketched one table describing the courses, which include course_code, name and every other relevant information. Then I sketched another table linking those courses to when they will be taught.
I am missing classes that are classified as all_year. Also I am missing a way how to label the courses under a major. Since hypothetically a course can belong to several majors, putting the data from one into the other would force you to duplicate data. Any ideas how I would implement this two things to my tables design? Or suggestion in how to restructure my design. If possible please show me a query to execute in my phpmyadmin DB.
Example of table courses
id serial
course_code text
description text
Example of table course_dates
id serial
course_id serial
year date
semester
Example of table majors
major_id int
course_id int
So a populated database could contain the following:
Table courses
id course_code description
1 INF1000 "Basic programming"
2 INF1001 "More basic programming"
Table course_dates (0 for spring 1 for fall)
id course_id year semester
1 1 2012 0
2 1 2013 1
3 2 2013 1
To link courses to majors - this is a one to many relationship (one course to many majors) - you want to use a linking table that has this type of structure:
table courses_majors
major_id int
course_id int
Remember to index this table as well - its very important. Then you can populate it and have one course even go to many majors and many course to one major (many to many relationship).
Then you can run a join on the tables across this table:
select * from courses left join courses_majors on courses.id = courses_majors.course_id left join majors on courses_majors.majors_id = majors.id
Of course you can add a where clause, etc.
The other way is to create a table of majors:
majors
id int
name varchar
Then add a major_id to your courses table - this will just give you a one to one relationship from courses to majors, but many courses can join a major.
As for Yearly, I would just add a field in the database to account for this, probably a tiny int and just make it 0 or 1.