Design suggestions for Teachers,subjects and grades database - database

As part of database design task for a high school, I am kind of stuck with classes table. The tables created so far are:
Students
--------------
Id
name
Grades (grade 1,2,....9,10)
------------------
id
description
term
Subjects (science,maths...)
-------------------
id
name
grade_subject (subjects tought in grades)
----------------
id
grade_id
subject_id
teacher
---------------------
id
name
teacher_subject (teachers who are assigned to teach subjects in particular grade)
---------------------
id
teacher_id
grade_subject_id
I am not confident about table design of teacher_subject table. This table makes use of id of grade_subject_id which might (not) be a good design. Should this table have two FKs , one grade_id and subject_id?
I also need further to store number of classes conducted on particular subject and grade by particular assigned teacher.
Would this table fit in this case:
Class (stores daily teaching schedule)
-----------------------------------
id
*teacher_id
grade_id
subject_id*
*or only teacher_subject_id from teacher_subject table*
date
start_time
end_time
status ( conducted/cancelled/postponed)+
And lastly, a table to store information about who attended the class
attandants
--------------------
student_id
class_id
Any suggestions would greatly be appreciated.

Data modelling is the art of representing the real world in a relationship diagram. Your mode is correct but is it true?
Consider, what is a CLASS? It's a TEACHER, a SUBJECT and a GRADE. Those are your relationships. In addition you want to enforce the rules that the SUBJECT is appropriate for that GRADE and that the TEACHER can teach that SUBJECT in that GRADE.
I think your problem lies in the use of surrogate keys in the intersection tables. These are the tables which represent your many-to-many relationships: teacher_subject, grade_subject. These are synthetic tables anyway, and they only consist of keys anyway. Hence a composite primary key will suffice.
Surrogate primary keys have no meaning, so we need to define a unique constraint on grade_subject(subject_id, grade_id) to ensure we don't have two records for ('PHYSICS', 'YEAR 2'). Given that grade_subject is an intersection table with no other columns adding a surrogate key is pointless. The value of surrogate keys is to minimise the impact of a business key changing. But grade_subject doesn't have a business key, just two surrogate keys, subject_id and grade_id.
This has an advantage when it comes to defining referential integrity.
So I would approach your problem this way:
grade_subject
----------------
grade_id
subject_id
primary key (grade_id, subject_id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
teacher_subject
---------------------
teacher_id
grade_id
subject_id
primary key (teacher_id,grade_id, subject_id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
foreign key (teacher_id) reference teacher (teacher_id)
foreign key (grade_id,subject_id) reference grade_subject (grade_id,subject_id)
Class
-----------------------------------
id
teacher_id
grade_id
subject_id
primary key (id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
foreign key (teacher_id) reference teacher (teacher_id)
foreign key (grade_id,subject_id) reference grade_subject (grade_id,subject_id)
foreign key (teacher_id,grade_id,subject_id) reference teacher_subject (teacher_id,grade_id,subject_id)
This may look like a pile up of foreign keys, and I can envisage some arguments at the review stage. (I include the foreign key on grade_subject so I've got something to concede which I don't care about that much and so could concede).
But I don't like having significant data relationships such as CLASS_SUBJECT obfuscated by being enforced through a subsidiary relationship such as TEACHER_SUBJECT. I don't want to have to join to TEACHER_SUBJECT and SUBJECT_GRADE in order to join CLASS to SUBJECT.
Now, why do I choose to include referential integrity constraints to the single parent tables and the intersection table when the latter indirectly enforces the former? Because it makes the relationships clearer in the model. I stress in the model, because in the physical database I might choose to omit the single table foreign keys, or disable them, and trust in the relational integrity of the intersection table.
Something about a triple column composite bugs me, and I think it's this: it's not sufficiently normalised. You may have a special case but the more general model would be two rules, TEACHER_SUBJECT and TEACHER_GRADE. That would look like this
teacher_subject
---------------------
teacher_id
subject_id
primary key (teacher_id, subject_id)
foreign key (subject_id) reference subject (subject_id)
foreign keye (teacher_id) reference teacher (teacher_id)
teacher_grade
---------------------
teacher_id
grade_id
primary key (teacher_id,grade_id)
foreign key (grade_id) reference grade (grade_id)
foreign key (teacher_id) reference teacher (teacher_id)
Class
-----------------------------------
id
teacher_id
grade_id
subject_id
primary key (id)
foreign key (grade_id) reference grade (grade_id)
foreign key (subject_id) reference subject (subject_id)
foreign key (teacher_id) reference teacher (teacher_id)
foreign key (grade_id,subject_id) reference grade_subject (grade_id,subject_id)
foreign key (teacher_id,subject_id) reference teacher_subject (teacher_id,subject_id)
foreign key (teacher_id,grade_id) reference teacher_grade (teacher_id,grade_id)
Of course, if you still wanted to enforce a rule that Mr Drury could only teach Maths to fourth formers and Physics to sixth formers you would need a TEACHER_SUBJECT_GRADE table.
One thing your data model doesn't address is the problem of scheduling. School timetables have to mesh, so Classes need to fit into a pre-determined grid. You probably need to define the timetable's slots as a separate table and link CLASS to that. Classes also need Classrooms. That's another table.

This model is typical for database designers when start learning how to create relational models.
Have a look at this site, contains tons of samples and some of those are applicable to the problem you are trying to solve
http://www.databaseanswers.org/data_models/
Check the section 218 Education

Related

How to create a ternary relationship that has a weak entity?

I am developing a system where there are doctor , patient and diagnosis.
I made diagnosis a weak entity because without a doctor or a patient there will not be a diagnosis.
now I want to make a relationship called treatment between doctor and patient and diagnosis where a specific doctor will treat a specific patient that has a specific diagnosis.
how to make the relationship given that diagnosis is a weak entity that will not have it's own primary key.
I think your fundamental understanding of weak entities and primary keys is flawed.
You seem to think that because the weak entity table "includes" the primary keys of two other tables, that means it can't have a primary key of its own.
This is not the case. A Primary Key can be the combination of multiple columns, as long as that combination is Unique for all rows.
Based on what you describe you should have something like this:
Table Doctor
Primary Key: DoctorID
Table Patient
Primary Key: PatientID
Table Diagnosis
Primary Key: DoctorID, PatientID (or an Identity column to form an artificial PK)
Foreign Key: DoctorID References Table Doctor
Foreign Key: PatientID References Table Patient
So finally,
Table Treatment
Primary Key: DoctorID, PatientID (, Identity column of Table Diagnosis if you created one)
Foreign Key: DoctorID References Table Doctor
Foreign Key: PatientID References Table Patient
This is sufficient if a doctor can only diagnose each patient once, and also can only suggest one treatment per patient. If either of these combinations can have more than one instance, then you should add some third "Line Number" type column to the PK of the Diagnosis and/or Treatment table to include in the PK for that table and make it unique.

Extending SQL Table

I have 4 SQL tables: User, Student, Professor and Publication.
User has the common columns for any kind of user;
Student has columns specific for a student;
Professor has columns specific for a professor;
Publication is only for professors.
So I have:
create table dbo.[User] (
Id int identity not null
constraint PK_User_Id primary key clustered (Id),
-- Other user columns
)
create table dbo.Student (
UserId int not null
constraint PK_Student_UserId primary key clustered (Id),
-- Other student columns
)
create table dbo.Professor (
UserId int not null
constraint PK_Professor_Id primary key clustered (Id),
-- Other student columns
)
create table dbo.Publication (
Id int identity not null
constraint PK_Publication_Id primary key clustered (Id),
UserId int not null
-- Other student columns
)
alter table dbo.Student
add constraint FK_Student_UserId foreign key (UserId) references dbo.[User](Id);
alter table dbo.Professor
add constraint FK_Professor_UserId foreign key (UserId) references dbo.[User](Id);
alter table dbo.Publication
add constraint FK_Publication_UserId foreign key (UserId) references dbo.Professor(Id);
QUESTION
Should I have a column Id as PK in Professor and Student tables?
And make, for example, (Id, UserId) as the PK of Professor (Same for student)
Then Publication would reference Professor.Id and not Professor.UserId.
I am asking this because it sounds strange to have Publication to reference UserId from Professor table which can be confusing when I will have more tables.
Could someone please advice me on this?
In your current schema arrangement and without knowing your use cases (programmatically), one could make the argument that you don't need the Id identity columns for any of the extension tables. I assume this would be a 1 to 1 relationship to the User table anyway, so you'd at least want a unique constraint on the UserID columns, which you'd get by making it a PK anyway.
Things I like to consider are:
Can a professor ever become a different user ?
Is it possible for a professor to exist without an user ?
Is it possible for a single user to be two professors (multiple disciplines?)
If so, why wouldn't you give every professor an unique Id (ProfessorId), and only create a foreign key to the User table (UserId, you could call this UserFk).
In the publication table you can reference the professor by his/her id and call this one ProfessorFk. This way you create very efficient references between tables. The publication table than also gets a single PublicationId as primary key.
Correct me if i'm wrong, i don't know your use case. But it would seem reasonable that a professor can have multiple publications, but a publication can also be written by multiple professors ? This would mean you need an extra table between publication and professor for the n-n relationship.
About creating a professor key that is a combined key (Id, UserId). I personally dislike combined keys, if you want to reference this professor from your publication table you need two columns.
This would also suggest you can have multiple professors for the same user, if so, go for the single Id option.
This means i would create the following setup:
User Table
UserId
Student Table
StudentId
UserFk
Professor Table
ProfessorId
UserFk
ProfessorPublication Table
ProfessorFk
PublicationFk
Publication Table
PublicationId
So, it partly is based on what you want to be able to do with your data, and partly just your preference.

Designing a simple database that respects the third normal form

I'm trying to accomplish 3NF or third normal form for a small database homework.
I have Students, Classes and Parents.
Here are the tables I need to make:
Student: id, name, grade (avg)
Class: class_id, profile (type of class), class_master, students within said class
Parent: name, address, student enrolled in school
Things that I should point out:
Since my english is not that good, I thought I should specify:
Class is one to many relationship since one student can be part of one class, and only one (thus a class is a collection of students, nothing else).
Profile is a specialization of a class (again, the student grouping mechanism called class). Ex: Profile: Mathematics, Literature, Computer Science
[/Things that I should point out]
Again, I have to make tables that fall within 3NF guidelines, not tables that are exactly like the ones I have just mentioned
I was thinking:
Class:
class_id primary key, foreign key (class_master_name)
Profile:
class_master_name primary key, profile_name
Student:
student_id primary key, name, grade (avg), foreign key (class_id)
Parent:
parent_id primary key, name, address
Thus Class, Profile, Student and Parent would be 3NF since all non key elements refer strictly to the key, the whole key, and nothing but the key.
My problems (or rather specific questions that need answers):
Is the student <-> class relationship OK ? Is it enough that student refers to class ? I could not imagine a way class could have references towards the students without having repeating data that would either conflict with 2NF or 1NF.
Each student has up to two parents (one, or both could be dead or simply unknown). I was thinking of having a table Relationship: student_id, parent_1_id, parent_2_id but I have no idea how to implement this. How could I (in SQL Server Management Studio 2008) make this table (where parent_1_id != parent_2_id and also student_id is the primary key but also a foreign key)
Would this actually be 3NF or am I doing something wrong ?
How I thought of implementing Relationship: student_id, parent_1_id, parent_2_id
CREATE TABLE Relationship (
student_id int NOT NULL PRIMARY KEY,
parent_1_id int,
parent_2_id int,
CONSTRAINT (parent_1_id, parent_2_id) FOREIGN KEY
REFERENCES Parent (parent_id, parent_id),
CONSTRAINT (student_id) FOREIGN KEY
REFERENCES Student (student_id)
)
Is it OK ?
Looks like you need something similar to this:
(Class.ProfileId and Student.ClassId are NOT NULL, while Parent1Id and Parent2Id are NULL-able.)
ClassType:
classtype (primary key)
name
etc...
Class:
classid (primary key)
classtype (foreign key)
classname
etc...
Person:
personid (primary key)
name
dob
etc....
ClassStudent:
studentid (primary key)
classid (foreign key)
personid (foreign key)
grade
etc
PersonRelation:
relationid (primary key)
prim_personid (foreign key)
sec_personid (foreign key)
relationship (parent, sibling, etc)
etc

Database problem--student registering for the same class twice..how to stop it Access 20007

I am making a mock database and I have a student table, student_class linking table, and a class table. How can I make it so that a student cannot be registered for the same class twice?
Example: StudentID 21 and classID 34 can be entered X number of times in the linking table.
The tables are designed 3NF, too.
In your student_class linking table (otherwise called a composite table), make both values, StudentID and ClassID, primary keys. So that table will have 2 columns that are composite primary keys and also foreign keys to their associated tables. Does that make sense?
A student_class table probably has at least two columns. One would be a foreign key to the primary key in student; the other would be a foreign key to the primary key in class. You need a primary key constraint on that pair of columns.
For example, if student_class had the two columns student_id and class_id . . .
Open the table student_class in design view.
Select both those columns.
Click the key icon.
That should do it.
You could have a table that tells you which students are enrolled in which classes, named students_classes. If you make a composite primary key on this table containing student_id and class_id, then it should be impossible to have the database contain a student in the same class twice.
I should point out that you should not have an auto-increment ID primary key column on this table (I think Access likes to add this by default so if it did you may have to remove it). If you do, you could still end up with duplicates if all three are a part of the key. Example:
ID student_id class_id
113 1 2
114 1 2
Having the ID field still allows you have a student enrolled twice in the same class.

When should I combine two foreign keys as a single foreign key?

My teach said I should combine two foreign keys into a single primary key. But my thought process is that that would allow for only one combination of each foreign key.
Imagine I have a Product, Purchase, PurchaseDetail.
In PurchaseDetail I have two foreign keys, one for product and one for purchase. My teacher said that I should combine these two foreign keys into a single one. But can't a product be in many different purchases? And many purchases have many products?
I'm confused.
Thanks!
Edit: This is the SQL my teacher saw and then gave feedback upon. Thanks for the guidance guys. (I changed the essential to English)
create table Purchase
(
ID int primary key identity(1,1),
IDCliente int foreign key references Cliente(ID),
IDEmpleado int foreign key references Empleado(ID),
Fecha datetime not null,
Hora datetime not null,
Amount float not null,
)
create table PurchaseDetail
(
ID int primary key identity(1,1),
IDPurchase int foreign key references Purchase(ID),
IDProductOffering int foreign key references ProductOffering(ID),
Quantity int not null
)
create table Product
(
ID int primary key identity(1,1),
IDProveedor int foreign key references Proveedor(ID),
Nombre nvarchar(256) not null,
IDSubcategoria int foreign key references Subcategoria(ID),
IDMarca int foreign key references Marca(ID),
Fotografia nvarchar(1024) not null
)
create table ProductOffering
(
ID int primary key identity(1,1),
IDProduct int foreign key references Product(ID),
Price float not null,
OfferDate datetime not null,
)
Maybe I'm confused about good database schema design. Thanks again!
I imagine he's suggesting:
Product - one primary key (product id), which implies a unique product id
Purchase - one primary key (purchase id), which implies a unique purchase id
PurchaseDetail - two foreign keys (product id),(purchase id), plus one unique constraint on (product id + purchase id)
Plus some people argue that all tables should have their own primary key that doesn't depend on anything else (purchase detail id). Some DBMS make this mandatory.
This means that you can't have two rows in PurchaseDetail that have the same product and purchase. That makes sense, assuming there is also a quantity column on PurchaseDetail, so that one purchase can have more than one of each product.
Note that there is a difference between a unique constraint and a foreign key. A foreign key merely says that there should be an item with that id in the parent table - it will let you create as many references to that item as you want in the child table. You need to specify that the column or combination of columns are unique if you want to avoid duplicates. A primary key on the other hand implies a unique constraint.
Exact syntax for defining all of this varies by language, but those are the principles.
I don't agree with the single key, but they could be a compound key (which I tend to dislike). They can be two different fields each restricted to the ID in the corresponding tables.
Not sure why the same product iD would need to be listed more than once for a single purchase? Isn't that why you indicate quantity? Maybe the need to do a separate line item for a purchase and a discount?
I believe thelem has answered correctly. But there is another option. You could add a new primary key column to the details table, so it looks like this:
detail_id int (PK)
product_id int (FK)
purchsae_id int (FK)
This is not really necessary, but it could be useful if you need to ever need to reference the details table as a foreign key - having a single primary key field makes for smaller indexes and foreign key reference (and they are a little easier to type).
That depends on what data you need to represent.
If you use the two foreign keys as the primary key for the purchase detail, a product may only occur once in each purchase. A purchase may however still contain many products, and a product may still occur in many purchases.
If the purchase detail contains more information, you may need to be able to use a product more than once in a purchase. For example if the purchase detail contains size and color, and you want to by a red T-shirt size XL and a blue T-shirt size S.
Perhaps he is suggesting a many-to-many table where it's Primary Key is comprised of the Foreign Keys to the mapped tables:
PurchaseDetail:
ProductId int (FK)
PurchaseId int (FK)
PK(ProductId, PurchaseId)
This can also be modelled as
PurchaseDetail:
PurchaseDetailId int (PK, Identity)
ProductId int (FK)
PurchaseId int (FK)
The second form is useful if you want to refer to Purchase details elsewhere in your model, and also in some RDBMS's it is beneficial to have a PK on a montonically increasing integer.

Resources