I am new to using databases and am trying to design a new database where I think I need a one-to-one relationship spread across many tables.
To demonstrate my design, let's say I am building a schedule database as an example. I start by creating a table for a person with a one-to-many relationship
CREATE TABLE person (
person_id SERIAL NOT NULL,
name VARCHAR,
PRIMARY KEY (person_id)
);
Next, I create a table of events which contains the many portion of the person relationship
CREATE TABLE events (
event_id SERIAL NOT NULL,
type VARCHAR,
name VARCHAR,
person_id INTEGER,
time TIMESTAMP WITHOUT TIME ZONE,
PRIMARY KEY (event_id),
FOREIGN KEY(person_id) REFERENCES person (person_id)
);
Now lets say I have two different types of events that have different information about them, say meal and homework
CREATE TABLE meals (
event_id INTEGER NOT NULL,
food VARCHAR,
utensils VARCHAR,
PRIMARY KEY (event_id),
FOREIGN KEY(event_id) REFERENCES events (event_id)
);
CREATE TABLE homework (
event_id INTEGER NOT NULL,
subject VARCHAR,
completed BOOLEAN,
score FLOAT,
PRIMARY KEY (event_id),
FOREIGN KEY(event_id) REFERENCES events (event_id)
);
Now, the reason I'm trying to design my database this way is because sometimes, you may just want to display a basic list of events for each person, regardless of what that event is. For instance, if I initialize my tables as follows
INSERT INTO person (name) VALUES ('Brad');
INSERT INTO events (type, name, person_id, time) VALUES ('meal', 'lunch', 1, '12/28/2016 12:00:00')
INSERT INTO events (type, name, person_id, time) VALUES ('meal', 'breakfast', 1, '12/28/2016 12:00:00');
INSERT INTO meals (event_id, food, utensils) VALUES (1, 'eggs', 'fork');
INSERT INTO meals (event_id, food, utensils) VALUES (2, 'turkey sandwich', 'hands');
INSERT INTO events (type, name, person_id, time) VALUES ('homework', 'final project', 1, '12/28/2016 18:00:00');
INSERT INTO homework (event_id, subject, completed, score) VALUES (3, 'Math', 'T', 0.93);
Then I may want to generate a list of all events for Brad
SELECT (events.time, events.type, events.name) FROM events
LEFT JOIN person ON person.person_id = events.person_id
WHERE person.name = 'Brad';
That is all easy, where I'm confused is, what if I want to see what Brad has eaten. I think I could probably use two JOIN
statements between person
and events
and events
and meals
, but what if I just want to walk through Brads events and get all of the extra information about each event, (for instance, if the event is a meal, tell me what he ate, if it is homework, tell me the score he got)?
Overall I have a couple questions.
- Is this a good database design or is there something else I should consider? Each of the potential use cases above, plus a couple more are all standard things I will need to use the database for.
- How can I easily determine which table to look in for more information for any given event in the events table? A couple of thoughts here -- I could store the name of the other table that contains more information about the event in the events table (ie, replace the
type
column with atable
column) but I think I read somewhere that was a bad idea.
A couple other notes, I am using Postgresql for the database. The actual database I'm building has a lot more detailed information for each table outside of what I've shown here. I was just trying to give an idea of what I'm trying to get to. Finally, I am building/accessing the database using sqlalchemy's ORM, so if there's a nifty trick I can do using relationships
that would help with this that would be really useful to know as well.