Database Design - Storing Requirements - mysql

Suppose we want to store university courses and their entry requirements in a database. So for example BSc Mathematics, BSc Fine Art, MSc Computer Science etc.
Each course has it's own set of requirements, and might have a different number of non-shared requirements. For example, to be eligible for the BSc Maths you might need a A in Maths and a B in Physics. Whereas the BSc Fine Art might require a A in Art and that the user has a portfolio. The MSc might have a minimum age of 25 etc.
Suppose we then have a student who has his own set of attributes. So they might have a A in Maths and a B in Physics and a C in Chemistry and be of age 19.
How can we structure our database such that it is geared towards efficient lookups. And given a student's attributes how can we retrieve all the courses which they are eligible for?
On an abstract level we are looking for all items whose requirements are a subset of the attributes given.
I'd like to implement this in MySQL. The schema could be:
courses
id
name
requirements
course_id
subject
grade
But then how to do query the table to get all eligible courses when the student has a A in Subject 1, a B in Subject 2 etc.
For a course to be a match, each one of its requirements must be satisfied.
Thanks in advance, I hope my explanation isn't too confusing.

Okay. I think you need a subject list, with a bunch of subject id's.
Now, for the query, you will start with (or generate) a bunch of subject id's and grades. The easiest thing to do is to make this into a temporary table with those columns.
Now, you can do your query, joining the subject id's, and adding a "where temp.grade <= course.grade.
The trick to this is to count the rows. If it has the same number of rows as the course has specified, then you have a successful match.
Is that enough to get you going?

Related

SQL attendance database design

I am currently designing a database in mariaDb that will be used in a Meteor app (woth sequelize orm) for tracking the attendance of students in a school.
I'm not sure is the most effective way as there are few exceptions on my case:
teachers can move and reorganise their schedule as they please, and also because the student pay for each lesson (and certain type of absence), I can't use a "exclusion way" (eg only record absence, so no record = present)
the most important query needed is attendance per student, and I need to have it every time I open my app for every student.
second most important is a monthly attendance per teacher. (This one is needed on demand)
(not db related) I need to track the students presence by groups of 10 (every lessons they have to pay again)
The estimated starting size is 20 teachers, 250 students, 500 attendance/week, (every student has two lessons) 37 weeks,( max size double students and lessons).
Is running 250 queries (find) on a 20000row table time consuming?
Is on student table having a lesson_counter field that is updated every time an attendance is recorded a good idea?
Many thanks!
UPDATE:
there is a possible optimization to be made? This should represent a base for a possible email and invoice system both towards students and teachers
There are many possible improvements to your design. Let me start by answering your specific questions:
Is running 250 queries (find) on a 20000row table time consuming?
No. On modern hardware, querying 20.000 rows is going to be fast. If you have a decent indexing strategy, the queries should return in 10s of milliseconds.
Is on student table having a lesson_counter field that is updated
every time an attendance is recorded a good idea?
No, it's a bad idea - on the assumption that you want a report for each student showing when they attended or missed a lesson, you have to store that data anyway. Keeping a counter is duplicating that information.
I suggest a design like the following.
An "attendance" and "absence" are logically separate things; you can model them in a single table with a flag. I've modeled them separately because I see them as different things in the business domain, with different attributes (absence has a reason code), and potentially different behaviour (for instance, an absence might have a workflow for sending an email). I prefer to have things that are logically separate in separate tables.
Student
-------
student_id
name
...
Lesson
------
lesson_id
subject
teacher_id (if only one teacher can teach a lesson)
....
enrollment
---------
lesson_id
student_id
start_datetime (or you might have the concept of "term")
end_datetime
lesson_session
-------
lesson_session_id
lesson_id
start_datetime
end_datetime
location
teacher_id (in case more than one teacher can teach a lesson)
attendance
--------
lesson_session_id
student_id
absence
------------
lesson_session_id
student_id
reason (or might be a foreign key to reasons table)

ER diagram for public school system

I have these set of requirement:
For each school, the system needs to keep track of its unique name, address, classification (Value could be Elementary, Middle, or High), and number of students studying in it.
For each School System Employee, we need to keep track of the unique employee number, full name, address, salary, and the school where (s)he works. An individual works only in one school.
For each student, we keep track of the student’s name (at times, we need to refer to student’s first name, middle initial, and last name individually), address (at times, we need to refer to the street address, city, state, and zip code individually), the school (s)he attends, and what grade (s)he is in.
The system sends letters to High School students frequently, and hence, needs to keep track of each High School student along with the year when (s)he enrolled in the High School.
A system-wide list of courses offered is kept. Information about a course consists of its unique number, unique title, and number of credits.
For each school, the information about which courses are taught there is kept.
For each student, we keep a grade report that provides the grade (Value could be A, B, C, D, or F) for the student for a specific course.
The School System owns buses which are identified uniquely by their registration numbers. Some students take them to commute between their home and their school, while others use their personal means to commute. We keep track of which student takes which bus to commute. We also keep track of drivers assigned to buses (a driver is a school system employee who could be assigned to multiple buses, and a bus could have multiple drivers assigned to it – consider this a weekly assignment of buses and drivers).
Here is my attempt at the ER design:
This is my first ER design and i just wanted to know if met all the requirements and if I did it correctly? Any help will be much appreciated! Thanks!
First of all I don't like it to omit columns necessary for forein keys, e.g. a school ID in the employee table. But I don't know enough about ER diagrams to say if that would even be allowed.
The diagram looks fine to me. Some points though:
School names can change. If there is a number system available (such as NCES School ID for USA) I'd make this the PK instead.
Numbers of students must be no column in the school table; the number of students per school is implicitly given by the students related to the school.
I don't like 1:1 relations very much. Student <-> High Schooler is okay, but I'd rather have the enrollment date in the students table.
StudentID alone can't possible the PK for the grades table. It must be StudentID + Course# instead.
The line from student to course is superfluous, because the relation is given by the grades table already (which is a bridge table containing StudentID, Course# and an optional grade).
The course table's PK must not be Course# + Title, because that would mean the same course number would be allowed in combination with different titles. The PK should be the course number alone. As to the relation: I don't know if the same course can be taught at different schools. If so, the relations are correct.
Met. (though I'd break appart address into # StreetAddress, PO Box, city, state zip etc.(assuming US) Though if you want extra credit you could subtype addresses into their own table and simply have the employee, student and school addresses all in one table with a foreign key...
I'd break down Name, address just as habbit always go to
the loweest common denominator: Fname, LName, etc... (for scaling
solutions long term; combining data is easy, breaking it out later
is hard)
Looks good
Doesn't grade define Highschool? a 9th
grader is in highschool right? so why a seperate table?
4.1) now a table which lists what letters were sent to what students might be useful... but they didn't say they needed this so I'd seek clarification on the requirement.
if # is unique title doens't need to be part
of key.
Missing (you need a schoolCourses table)
Missing (I guess could be handled through your grade table though) Id call the table studentcourses and keep grade on the table... then yeah it works.
Associative/Junction table between bus/student and bus/employee
needed
Overall many-to-many need to be resolved as part of modeling. and I agree with Thorsten, I want to see all fields in all tables including the FK's and I've done enough to know the CASE tools allow it.
and while 1-1 relationships look good for 4/5th normal form. they generally are not practical anymore unless the truely represent a separate concept. So I may have a vehicle table for a vehicle database but I may also have a table for car attributes vs motorcycle attributes vs truck vs boat etc... but vehicle is the primary in this case there so little reason to separate out high school I just don't see the long term value of keeping the object separate (but maybe I just lack vision).
You'll learn that in ERD's the cardinality of the relationships between the data is THE MOST IMPORTANT (following datatype/size/scale precsion). Eliminating M-M relationships is a must. and everything really boils down to 1-M or 1-1 when your done.
Not sure what the line between the school/bus implies.... the buses are owned by the whole system... maybe you need a "System" table tie that to the schools and buses to the system. that way if you support multiple school systems you know which buses belong to what system and what schools are in what system...

Relational Database Design - Courses offered by universities

I am creating a database for universities in my country. Particular database of name of the courses offered by each university.
I think I must consider the following points to create a database
Possible names of courses, let's assume 100 courses.
Name of courses offered by one university, let's assume 60.
Number of courses offered by university may differ from one university to another. One may offer 60 courses and other may offer just 50. Courses may overlap.
How do I create a relational database between table of point no.1 and table of point no.2, considering the point no.3. Please suggest a design pattern for this.
Normally, you would have a table listing all the available courses (in all universities) and another table including the university and the course (one record for each combination) using the ID of the course from the first table. This, of course, is just a very basic description. You may also wish to have a table for universities, course instances (meaning, the same course may run several times during the year, even overlapping within the same university to cope with high number of students), etc.
You could have:
university_course, which is a type of course at a university
a course_category that broadly collects each type of course together
Many course rows, which give the names of a course within a category.
So:
university_course.university_id -> university.id (a university has many university courses)
university_course.category_id -> category.id (a university course has one category)
course.category_id -> category.id (a category has many courses)
Thus, the set of courses (Computer Science, Networking, Computer Studies, Computer Hardware) can map to a category (Computer Science) and then each university course points to the category.

Redundancy vs. Flexibility

I am new to MySQL database and I'm collaborating with my former CSCI teacher to make a student database that holds his student grades history. My original idea was to have a Students table (studentID, firstname, lastname, middlename, gender), a Course table (courseID, course_description), a Grades table (studentID, courseID, year, final_grade), and then tables for AssignmentScores, TestScores, QuizScores, and ExerciseScores. Each of these tables would of course have a studentID, courseID, year, and section (code used by the school to define the semester and period) field, along with the scores earned by the students.
The problem with this approach is that in a perfect world, all courses would have the same number of assignments, exercises, tests, and quizes, and they all would have the same point value, however, as we all know, this is not a perfect world. For instance, there are a couple of courses that have assignments labeled 1a, and 1b both worth five points each as opposed to the normal 10 points each for 10 assignments (labeled 1 through 10). This is also the first year he started keeping track of exercises, and all classes do not have the same number of exercises, nor are they always worth the same point value.
In order to allow for flexibility, we decided to make a table containing general course information with a courseID, year, section, type (to designate quiz, assignment, test, or exercise), number (1a, 1b, or 1,2,3 etc...), and a maxpoints field (to hold the max point value per item). We would then also have a table for individual scores which would have basically the same fields but instead of max points there would an earnedpoints field (to hold the students scores on a particular item). He would then of course have to enter every courses details, every year, regardless of if it was different then the previous year's.
For the two courses he is currently teaching, that amounts to 90 rows per table with much of the data seemingly redundant.
Doing it this way seems to have a lot of redundant information, but I don't see any other way that allows for past, present, or future flexibility. One of the reasons I am doing this project is in hopes of using it to show prospective employers and I thought the point of a relational database was to minimize redundant information, and I don't want prospective employers to look at this and say, "what an idiot."
So my question to the stackoverflow community is, "is there a better way to do this?"

Access DB one ID, multiple classes and associated dates

I'm creating a DB for my office. We have about 200 employees. Each employee was required to complete at least 1 of 12 courses within 2 years of being hired (so different completion/qualification dates for every course, some people have been here 20 years, some just 1 year) to become qualified. Some have completed multiple courses. Each course has to be refreshed periodically (each refresh period is different and based on the last refresher date). I'm having trouble with the layout of the table. Here's what I have as an idea, but i'm trying to see if there is a less busy way to lay out the data. I want to be able to run a query that tells me what person has completed what class (so it would have to look at all 3 class columns). I also want to be able to tell when their qualification has lapsed, or is coming up. So far I've created an employee data table that looks like the table below.
ID Name Class1 Class2 Class3 QualDt-Cl1 QualDt-Cl2 QualDt-Cl3 LstRequal1 ...
1 Bob Art Spanish 3/17/1989 9/12/2010 3/8/2012
2 Sally Math 8/31/2012
3 George Physics History 2/6/2005 7/6/1996
4 Casey History 6/8/2000
5 Joe English Sports Physics 12/10/1993 10/15/2001 4/22/2006
The classes are listed in their own table and each class column pulls from that. The qual date refresher will be a calculated column in the query based on the last refresher date.
Is there a way to put all the classes one person is qualified for in one column and have the associated date for requalifiing for each particular cours in another column?
I think it would be less confusing if you had a table per subject and register the people's names under each one with the date passed.
Also it would probably help to declutter the table from uneccssary info like the exact date the exam was passed, you can do month and year or maybe just year? if the lee way is 2 years that would probably make more sense - also making the qulified calculation easier.
The query would work if you searched per subject maybe ? or who would qualify to do what subject this current year and then the next.
this is not much of a question that you would ask on here by the way - but hope the answer helps.
When designing a database, any time you find yourself adding columns with names like Class1, Class2, Class3 you should immediately stop and think about whether it makes more sense to put those columns in a separate child table called Classes with a link (relation) to the parent. There are several reasons for this, including:
What happens when somebody takes a fourth course? Saying "that will never happen" ignores the fact that "never is a very long time" and none of us can predict the future.
When checking whether or not someone has taken a course you really need to check (Class1 IS NULL) OR (Class2 IS NULL) OR (Class3 IS NULL) and that can get really tedious, It also means that if you do have to add Class4 then all of that SQL code has to be corrected.
Similarly, if you want to find someone who took "CPR" you'd have to look for people with (Class1 = 'CPR') OR (Class2 = 'CPR') OR (Class3 = 'CPR'). Yuck.
So, save yourself some trouble (a lot of trouble, really) and create a Classes table:
ID
ClassName
QualDate
(etc. )
...where ID is the ID number from the main table (what is called a "foreign key"). From your sample data, your Classes table would look something like this:
ID ClassName QualDate
1 Art 3/17/1989
1 Spanish 9/12/2010
2 Math 8/31/2012
3 Physics 2/6/2005
3 History 7/6/1996
...