How to create a ternary relationship that has a weak entity? - sql-server

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.

Related

Have a relationship between one table with one primary key and another with two primary keys?

I'm asking about this generally, but I'll give an example for illustration purposes.
Table1 has the following columns:
ID (Pk)
Order_Desc
Order_DT
Table2 has the following columns:
ID (PK)
Product_Code (PK)
Product_Desc
Is it possible for me to have relationship between Table1 and Table2. If so, how would you do this in SQL without you running into an error? Would you be able to create a relationship if the Product Code or ID was not a primary key? Instead, it was a foreign key?
Your table2 does not have two primary keys - it has ONE primary key made up from 2 columns. Any relational table NEVER has more than one primary key - it's just not possible at all.
Any FK relationship to that table must include all the columns that the PK of the referenced table has - so any FK to Table2 must include both ID and Product_Code.
It's an all or nothing proposition - either your foreign key includes all columns of the referenced tables primary key - or you cannot establish a FK-relationship.

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.

SQL Server - Foreign Key Referencing Primary Key A OR B

Say I have a table called Matchup that contains two sports teams. I also have a table called Pick that has a column that must match either Team_A OR Team_B. So it's a foreign key of one OR the other columns in Matchup. Is this possible?
Matchup
Team_A
Team_B
Pick
Pick_Team - FK Matchup (Must match Team_A or Team_B from Matchup).
I would split your Matchup table into two: Matchup proper and MatchupDetails.
The Matchup table would have a MatchupID column as its primary key.
The MatchupDetails one would consist of at least two columns: MatchupID to reference the Matchup table and TeamID to reference the Team table (you do have one, don't you?). The two columns would form the table's composite primary key.
Finally, there would be this Pick table. Since you've got multiple users (as per one of your comments), there would need to be a UserID reference. Two more columns, MatchupID & TeamID would serve as a composite foreign key referencing the corresponding column set in MatchupDetails. And to ensure that one user can pick no more than one team from a match-up, a composite primary key of (UserID, MatchupID) should do.
To summarise, here's a complete outline of the relevant part of the schema:
Matchup:
MatchupID
PRIMARY KEY (MatchupID)
MatchupDetails:
MatchupID
TeamID
FOREIGN KEY (MatchupID)
FOREIGN KEY (TeamID)
PRIMARY KEY (MatchupID, TeamID)
Pick:
UserID
MatchupID
TeamID
FOREIGN KEY (UserID)
FOREIGN KEY (MatchupID, TeamID)
PRIMARY KEY (UserID, MatchupID)
I dont think that this is the correct approach.
I would rather recomend that you add an additional field to table Matchup (lets say Pick) and add a CHECK CONSTRAINT to ensure that it is either Team_A or Team_B.
CHECK constraints enforce domain integrity by limiting the values that
are accepted by one or more columns. You can create a CHECK constraint
with any logical (Boolean) expression that returns TRUE or FALSE based
on the logical operators.
From FOREIGN KEY Constraints
In a foreign key reference, a link is created between two tables when
the column or columns that hold the primary key value for one table
are referenced by the column or columns in another table. This column
becomes a foreign key in the second table.
And it does not seem to be what you are looking for.

Design suggestions for Teachers,subjects and grades 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

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