Database: Tables design/structure - mysql

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.

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

Table Relations sql, php

I'm building a database driven management system in php. I've created two separate tables. One table has a list of student names and personal information. The other table is used to store notes. Example: If a student comes in to get advised, the adviser can create one or more notes for the student they're helping. What's the best way to link a note with a student id so the adviser can see the old notes and new notes for the student they're advising: foreign key, inner join, or full outer join?
u askin for this ?
student table : student_id ,student_name
notes table : note_id , student_id, Date, Note

How to query against many tables in mySQL

I am designing a database application for an award. It has a 75 year history and numerous categories that have changed over time. Right now, the design I am thinking of has two kinds of tables:
entities
people
publishers
categories
novel
movie
author
artist
and such like. Each category has data particular to that category, for example:
NOVEL
title varchar(1024)
author int #FK into people table ID
publisher int #FK into publisher table ID
year year(4)
winner bool
or
ARTIST
name int
year year(4)
winner bool
So far so good. However, there are 38 (!) of these categories that have existed over time (some do not exist anymore) and I really can't imagine doing a query for say, all of the winners from 1963 by doing:
SELECT * from table1,table2,...,table38 WHERE year=1963 and winner=TRUE;
These tables will never be that large (each category usually has at most five nominees, so even after a 100 years, there would be at most 500 rows per table and at a lot less for the early ones that aren't continued). So this isn't a performance question. It is just that that query feels very, very wrong to me, if only because every query will have to be changed every time a new category is created or an old one removed. That happens every few years or so.
The questions then are:
is this query evidence that I've designed this wrong?
if not, is there a better way to do that query?
I keep thinking there must be some way to create a lookup table which pulls from other tables, but I could be misremembering. Is there some way of doing such a thing?
Many thanks,
Glenn
You could do that with 3 tables.
First one is entities. It contains data about all publishers/artist/etc.
entities
name varchar(1024)
publisher bool
Second is data where all data from all categories is stored.
data
title varchar(1024)
author/name int #FK into people table ID
publisher int #FK into publisher table ID
year year(4)
winner bool
category int #FK into category table ID
Third is category in which you can find all categories names with their IDs.
category
ID int
name varchar(1024)
Now you have to join only three tables.
select * from entities e, data d, category c where d.name=e.name and d.category=c.id and winner=bool and year=1963
You would better to have a table for categories where you can save category key value, or just normal category table and you can save the row's id only in other table:
for example,
Table: Category
columns: id, name, slug, status, active_since, inactive_since etc...
In slug, you can keep slugified form of cat to make it easy for queries and url: for example, Industry Innovations category will be saved as industry-innovations.
In status, keep 0 or 1 to show if it is active now. You can also keep dates when it was active and when became inactive in active_since and inactive_since fields.
When you search, you can search those have status 1 for example etc. I dont think your problem is complex and it is very simple for mysql to search when you join tables.
There are projects where dozens of tables are joined and it is ok.

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.