DB design Many to Many relationship with other tables - sql

Let's say I have Employee & Meeting tables.
Employee
-----------
id
name
Meeting
-----------
id
name
Employee_Meeting
-----------
id
employee_id
meeting_id
Now I need to add employee's tasks (or anything else) in that meeting. What is a best practice to do that? I could have a relationships like this:
Employee_Meeting_Task
-----------
Employee_Meeting_id
task_id
or
Employee_Tasks
-----------
id
employee_id
meeting_id
task_id
Are both these approaches valid from 'proper' database design point of view?
My concerns are:
Case 1: Most of the time if I remove employee from the meeting I need to remove his tasks in that meeting as well. Employee_Meeting_Task would enforced that by constraint.
Case 2: Sometimes employee participates some daily meeting and regularly does same tasks in that meeting. If he got sick for several days, I would like to remove him from the meeting, but I don't want to re-add his tasks to the meeting next time he participates it.

There are a couple of things you should look at. First, if it's possible for an employee to have a task that is not associated with a meeting, you might be in trouble. One way out of it is to have a record in the meeting table with a name like "not applicable". Another way is to take the meeting_id field out of the employee_tasks table. The best way depends on the requirement to associate tasks with meetings, which is something you have to ask your taskmaster about.
Next, for many to many tables, you don't need a separate id field. For example, for employee_meeting, the PK could be the employee_id and meeting_id.
Next, look at what you said for Case 2. If there is a daily meeting, would that not be one record in your meeting table for each day?

Related

SQL database structure with two changing properties

Let's assume I am building the backend of a university management software.
I have a users table with the following columns:
id
name
birthday
last_english_grade
last_it_grade
profs table columns:
id
name
birthday
I'd like to have a third table with which I can determine all professors teaching a student.
So I'd like to assign multiple teachers to each student.
Those Professors may change any time.
New students may be added any time too.
What's the best way to achieve this?
The canonical way to do this would be to introduce a third junction table, which exists mainly to relate users to professors:
users_profs (
user_id,
prof_id,
PRIMARY KEY (user_id, prof_id)
)
The primary key of this junction table is the combination of a user and professor ID. Note that this table is fairly lean, and avoids the problem of repeating metadata for a given user or professor. Rather, user/professor information remains in your two original tables, and does not get repeated.

Multiple Columns but only one join

I have searched through quite a few answers on this but I can't seem anything specific to this situation. Apologies if I have over looked this.
We have a calendar system we are re-coding to log events, holidays, absent days, MOT's, Inspections etc
Initially our calendar focused around people, so we had a join from the person table to the calendarDay, but now other tables from the database are required to have days assigned to them.
My plan was to have a junction table for each of the three tables needing joined - Person, Job and Vehicle, or, have an ID column in the Assignment junction table that has a column for Person_ID, Job_ID and Vehicle_ID fk's:
CalendarDayAssignment
ID CalendarDayID PersonID JobID VehicleID
so this table would contain a CalendarDay_ID and either a Person_ID, Job_ID or Vehicle_ID depending on which table has a day assigned to it, leaving two columns having a NULL. (These could be moved directly to the CalendarDay table actually, as days will not be shared)
My preference would be the later shown above as I would only need one table, rather than 3 (potentially more if more objects need days assigned to them), and the referential data integrity is intact also.
I know this may be subjective, but is this a reasonable way of accomplishing this? It seems easier to include more objects should the time come.
Just as a note to the above, we will be pulling different data from the Person, Job and Vehicle tables, so I can't see how to implement a one size fits all solutions that doesn't end up with redundant data from a coding POV. The Junction table will likely have only 10,000 rows per year added.

Preserve old record values in relational DB

What is the best approach for the following situation?
Assume, that we have the following tables:
Companies:
COMPANY_ID
COMPANY_NAME
People:
PERSON_ID
PERSON_NAME
FK_COMPANY_ID
Meetings:
MEETING_ID
MEETING_NAME
MEETING_DATE
FK1_PERSON_ID
FK2_PERSON_ID
We have the following data:
/* Companies */
1, Company #1
2, Company #2
3, Company #3
/* People */
1, Vasya Pupkin, 1
2, Petya Vasechkin, 2
/* Meetings */
1, Meeting #1, 2014-02-01, 1, 2
Now, imagine that the person from Company #1 changes his company to Company #3. This will be of course reflected in the meetings view due to relation through person. And therefore, in the view form of the meeting it will show incorrect data in terms of the past situation (when a person was working in another company).
So, my question is how to preserve the view data for the meeting that has already past?
Currently I see the following solution. Extend the Meetings table as follows:
MEETING_ID
MEETING_NAME
MEETING_DATE
FK1_PERSON_ID
FK2_PERSON_ID
FK1_COMPANY_ID
COMPANY_NAME_1
FK2_COMPANY_ID
COMPANY_NAME_2
So that for historical purposes it will be possible to select the company_name_1 and company_name_2 rather than check actual person's company. And however, this would work even faster than relation, at the same time this moves me away from relational DB, and as this has to be used not just in one place, but in many places of a big project, it turns out that I will have a lot of data duplication.
Therefore, are there any better solutions for this problem?
UPDATE:
I see one possible solution in terms of relational DB. We need to introduce a new table:
Employments:
EMPLOYMENT_ID
FK_PERSON_ID
FK_COMPANY_ID
EMPLOYMENT_DATE
Assuming that a person can work only in a one company at the same time, we can know for sure, which company he worked in during the meeting. However, a small issue still exists: the company name (if renamed) will be the last one used. This can be fixed by the similar approach (if needed):
Company_Names:
FK_COMPANY_ID
COMPANY_NAME
ACTUAL_FROM_DATE
Seems that it adds some complexity but flexibility at the same time.
This is a standard problem that one encounters in real world databases. Your solution looks good. Keep in mind now, that to find out where some works you will need to do something like:
select * from employment where person_id=123 and
employment_date=(select max(employment_date)
from employment where person_id = 123)
That might be OK, but there are other solutions. For example, you can add a last_known column to employment and then your query for finding where a person works can now be:
select * from employment where person_id=123 and
last_known=1
There is a question https://stackoverflow.com/a/19144370/4350148 that may also be helpful.

How to express these model relationships

I'm not sure about the best way to express a relationship between models in my Laravel 4 application. I have three models that I am using to store information in a database: Employer, Employee and User. Basically, the Employer and Employee models are just going to contain meta information about the User model. I think the following expression is the best I can think of:
Employer has many Employee
Employee belongs to one Employer
Employer belongs to one User
Employee belongs to one User
In the database, I am going to have a user_id foreign key in both the employers and employees tables that reference the id field in the users table. Is this the best way to model this domain?
It depends. Can an employee have more than one employer? Can an employee be employed at more than one place? Do you want to delete records if an employee leaves (and lose history)?
If you can delete the employee record when the employee leaves you can just have an employer_id field in the employee table. But just be prepared that you won't be able to easily add capabilities if you need them in the future.
If you want to prepare for the future: You might want to have a table that says
employer_id
employee_id
start_date
end_date
And even then if an employee comes and then leaves you have records with the same employer_id, employee_id. So that makes it look like you need an internal key and have say:
employment_record_id // this is the primary key
employer_id
employee_id
start_date
end_date
I'm not sure exactly what users are but ask yourself the same types of questions:
Can a user exist with an employee record
Can you have employees without a user record
Can a employees user record change
Can a users employee record change

Access Appointment System

I'm trying to produce a Dr-patient appointment system. So far I have four tables:-
Patient:- Doctor:- Appointment:- Availability:-
patientID doctorName time time
name room date doctorName
address patientID
doctorName
All relationships are 1 to manys, with the many side coming out of the appointment table.
Patient:- The table for patient details
Doctor:- The table for doctor details
Appointment:- the table for appointments
Availability:- The table which stores timeslots each doctor is available
However this is all relatively new stuff to me and I'm getting quite thrown. Firstly in the doctors table should I have a field for DoctorID and use that as a primary key instead of the doctors name? Even though there's only likely to ever be a handful of records in that table.
Secondly if I was to change to DoctorID in all tables instead of the doctorName would I still easily able to access the doctorsName if and when required? This part is what confuses me, maybe I'm just over thinking these things.
The reason I ask is for example say I was to produce a report of an appointment which showed the doctorID, I should be able to get the doctors name for the report based on the relationship right? Likewise for the patient based on patient ID.
I'm guessing I also have enough information in the tables to check against and prevent appointment clashes.
Many thanks,
You really should use a doctorsid instead of a doctorsName. Because if you are planing to join these tables together then it is much better to join on ints then on varchars.
And another question if you are still going with the varchar solution what will happened if the doctor change its name (marriage or so). The you need to update the realted tables and the doctor table. If you then are going with the int you just have to change it in one place (the doctor table)
Yes and when you are going to produce you appointment report. You need to get the doctors name by joining the tables.
So your table structure should look something like this:
Patient:- Doctor:- Appointment:- Availability:-
patientID DoctorId AppointmentTime AvailabilityTime
PatientName room AppointmentDate DoctorId
address doctorName patientID
DoctorId