I have two tables DOCTORS and PATIENTS. I want both the doctors and the patients to have contact information (such as telephone numbers, addresses and so on) that aren't fixed. For example we can add multiple phones to either a doctor or a patient.
I thought about creating a separate table e.g. PHONES with fields phoneID, the phone number and a foreign key that points to a contact, such as below:
PHONES
phoneID [pk]
number
contactID [fk]
DOCTORS
docID [pk]
fname
sname
specialization
.
.
.
PATIENTS
patID [pk]
fname
sname
.
.
.
The first problem comes from the fact that the patID and the docID might (and will eventually) have the same value. So relating a phone to one and only one person becomes more difficult.
So far I've thought three possible solutions:
Have custom format primary keys for the doctors and patients. For example doctors could have ids in the form of "d00001", "d00002" and so on, and patients ids like "p00001", "p00002". My concern is this could complicate things unnecessarily.
Another solution would be to keep both doctors and patients in one table, and define if they are a doctor or a patient by using another field.
Create separate PHONE tables for doctors and patients, but that's even more clumsy.
Somehow I think both approaches are not the best. Any advice?
You could introduce a PERSON-table. This is 1:1 related to your doctors and patients (and later maybe to employees, suppliers, institutions, whatever). Let the contacts be related to this person-table.
Application code can model this with inheritance quite easily...
Within your person-table you keep some general information like DisplayName and PersonType (reference to a person-type-table with entries like Doctor, Patient and ...).
Keep this table slim...
If you have to choose out of your own ideas, I'd prefer the second. Keep them in one table and mark them with a type column. Avoid speaking keys...
You are thinking about the relationships wrong.
There is a many to many relationship between person and phone number.
A single person can have many different phone numbers (home, work, mobile, etc.)
A single phone number can be associated with many people (husband, wife, children, co-worker, ...)
I don't see why you need a primary entity with phone number as a primary or alternate key.
I would use 5 tables:
Doctor PK=DoctorID
Patient PK=PatientID
PhoneType PK=PhoneTypeCode
DoctorPhone PK=DoctorID,PhoneTypeCode,PhoneNum
FK1=Doctor.DoctorID
FK2=PhoneType.PhoneTypeCode
PatientPhone PK=PatientID,PhoneTypeCode,PhoneNum
FK1=Patient.PatientID
FK2=PhoneType.PhoneTypeCode
You might consider having distinct DoctorPhoneType and PatientPhoneType tables, given that the phone roles are likely to be different between the two classes of people.
Related
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.
I have 5 tables that have the same structure and same columns: id, name, description. So I wonder what is the best way to design or to avoid having 5 tables that have the same columns:
Create a category table that will include my three common
columns and another column "enum" that will differentiate my categories
ex (city, country, continent, etc.)
Create a category table that will include my three common
columns and create the other five tables that will just include an
id.
Note that I would have an assocation table that should include the id of cities, id countries, id continents, etc. so i can display them into a report
Thank you for your advice.
The decision on how many tables to have under these circumstances simply depends.
The most important factor is whether the five things are independent entities or whether they are related. A simple way to understand this is by understanding foreign key relationships: Will other tables have a column that could refer to any of the five (say "geoid")? Or will other tables have a column that generally refers to one of the five ("cityid", "countryid")? The ability to define helpful foreign key constraints often drives the table structure.
There are other considerations. If your data is at the geographic level, then it might represent hierarchies . . . cities are in countries, countries are on continents. Some databases (such as MySQL) do not support hierarchical queries at all. Under these circumstances, you might consider denormalizing the data for querying purposes.
Other considerations can also come into play. If your application is going to be internationalized, then having all the reference tables in a single place is handy -- for providing cultural-specific information (language, currency symbol, and so on). One way of handling this situation is to put all such references in a single table (and perhaps using more sophisticated foreign key relationships).
The column names are not important, just the data in the columns. If City description, country description and continent description are different information then you are already doing this the right way. The only time you would aim to reduce this data would be if you were repeating information but for the titles of the data it's fine.
In fact. You are doing this correctly. Country will have different values from city for every field mentioned. Id is just an id, every table should have one. Name and description wont be the same across country and city.
Also, this way if you want a countrys name you dont have to go through every country, continent and city. You only have 192 or so entries to go through. If you had all of that in one massive table you would have to use it for everything and go through every result every time you want data. You would also have to distinguish between cities, countries and continents in some other way than the separate tables.
Eg:
method 1, with 5 tables:
SELECT * FROM country
does the same as
method 2, 1 table:
SELECT * FROM table WHERE enumvalue = 'country';
If you have tables representing city, country and continent, and they all have exactly the same fields, you have a fundamental problem. In real life, every city is in a country and every country is in at least one continent (more or less) but your data structure does not reflect that. Your city table should look something like this:
id (primary key)
countryId (foreign key to country)
name
other fields
You'll need a similar relationship between countries and continents. However, before you do so, you have to decide what to do about countries like Russia which is in two continents and Palau which isn't really in any.
You may also want to have a provinceStateTerritory table to help you sort out the 38 places in the United States named Springfield. Or, you may want to handle that situation differently.
I am making a quiz-program. In a quiz I have many participants, but on the other hand participants can enter many quizzes (over time). So I have overcome this many-to-many relationship with a linking table. So far I can understand.. now for the difficulty for me: a participant can either be a group, or a single player.
So a quiz has a participant (with a linking table) and this participant is either a group which has several persons, or this participant is a player and only one single person.
table Quiz : PrimaryKey = quiz_id, (name, date,... )
table QuizParticipant : PrimaryKey = quiz_participant_id, quiz_id
table ParticipantGroup : PrimaryKey = quiz_participant_id, group_id
table participantPlayer : PrimaryKey = quiz_participant_id, person_id
The problem for me is: how do I query all participants of a quiz by quiz_id, and preferably sort them by type (group or player)?
Tips on how to google this stuff are usefull as well :)
It's an interesting design decision. The way you proceed can shape your entire application.
My advice is to record the participant type within each occurance of participation. This would be either "GROUP" or "PLAYER" and would define whether the ParticipantID referred to a GroupID or a PlayerID. This will result in the cleanest database design and application logic in the end.
So your tables look like:
Quiz (QuizID,QuizName)
QuizParticipation (ParticipationID, ParticipantType, ParticipantID)
Group (GroupID,GroupName)
GroupMembers(GroupID,PlayerID)
Player(PlayerID,Name)
You might need to make a custom constraint to ensure that duplicates cannot be created within the ParticipantID and ParticipationType combined fields of the QuizParticipation table, or manage the generation of primary keys carefully.
My suggestion is to always link your quizzes to groups (many to many) and treat single players as a group of 1. So your groups are linked to players (also many to many)
If a person can belong to many groups and a group can have many people, that's another many to many relationship. Since you know how to create these linking tables, create one for this relationship.
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
I have some tables that benefit from many-to-many tables. For example the team table.
Team member can hold more than one 'position' in the team, all the positions are listed in the position db table. The previous positions held are also stored for this I have a separate table, so I have
member table (containing team details)
positions table (containing positions)
member_to_positions table (id of member and id of position)
member_to_previous_positions (id of member and id of position)
Simple, however the crux comes now that a team member can belong to many teams aghhh.
I already have a team_to_member look-up table.
Now the problem comes how do I tie a position to a team? A member may have been team leader on one team, and is currently team radio man and press officer on a different team. How do I just pull the info per member to show his current position, but also his past history including past teams.
Do I need to add a position_to team table and somehow cross reference that, or can I add the team to the member to positions table?
It's all very confusing, this normalization.
Yes, a many-to-many junction table can have additional attributes (columns).
For example, if there's a table called PassengerFlight table that's keyed by PassengerID and FlightID, there could be a third column showing the status of the given passenger on the given flight. Two different statuses might be "confirmed" and "wait listed", each of them coded somehow.
In addition, there can be ternary relationships, relationships that involve three entities and not just two. These tables are going to have three foreign keys that taken together are the primary key for the relationship table.
It's perfectly legitimate to have a TeamPositionMember table, with the columns
Team_Id
Position_Code
Member_Id
Start_Date
End_Date NULLABLE
And and a surrogate ID column for Primary Key if you want; otherwise it's a 3-field composite Primary Key. (You'll want a uniqueness constraint on this anyway.)
With this arrangement, you can have a team with any set of positions. A team can have zero or more persons per position. A person can fill zero or more positions for zero or more teams.
EDIT:
If you want dates, just revise as shown above, and add Start_Date to the PK to allow the same person to hold the same position at different times.
My first thought:
Give your many-to-many teams/members table an ID column. Every team-to-member relationship now has an ID.
Then create a many-to-many linking positions to team-member relationships.
This way, teams can have multiple members, members can have multiple teams, and members can have multiple positions on a per-team basis.
Now everything is nice and DRY, and all the linking up seems to work. Does that sound right to anyone else?
Sounds like you need a many-to-many positions to teams table now.
Your team_to_member table can indeed have an extra column position_id to describe (or in this case point to) the position the member has within that team.
Get rid of member_to_previous_position table. Just use member_to_positions and have these columns:
MemberToPositionID (autoincrement OK only)
MemberID
PositionID
StartDate
EndDate
Then to find current positions, you do:
select *
from member_to_positions
where EndDate is null