Reputation: 24305
I'm wondering about the pros and cons of storing my users and their groups in 3 tables vs. 2 tables.
Pros of 2 tables
Pros of 3 tables
groups
table would be more explicit so this might be easier for developers to understand/maintain.Cons of 3 tables 1. Violating DRY principles across application code by not doing the #1 in the "Pros of 2 tables" above.
What else should I be thinking of?
The 2 mandatory tables are a users
table and a group_member
table.
+---------+ +------------+
| users | | group_member | +----------+
+---------+ +------------+ | groups |
| user_id |----->| user_id | +----------+
| name | | group_id |<----| group_id |
| pass | +------------+ | name |
| ... | | ... |
+---------+ +----------+
**theoretical 3rd table**
note: The user_id
and the group_id
in the group_member
table would both be
referring to the user_id
in the users
table
Upvotes: 0
Views: 250
Reputation: 70470
Main point: if you want to store users & groups in one table as they share (most) characteristics, this is perfectly valid. However, this would mean that technically a group can be a member of a user, and you can't enforce on a database level that users can be in groups and not the other wary around:
Scenario in 1 table:
CREATE TABLE users_and_groups (id int...
CREATE TABLE group_members (
group_id,
user_id
FOREIGN KEY (group_id) REFERENCES users_and_group (id) -- no way to limit on only groups
FOREIGN KEY (user_id) REFERENCES users_and_group (id) -- no way to limit on only users
)
Scenario in 2 tables:
CREATE TABLE users (id int...
CREATE TABLE groups (id int...
CREATE TABLE group_members (
group_id,
user_id
FOREIGN KEY (group_id) REFERENCES groups (id) -- guarantees a group
FOREIGN KEY (user_id) REFERENCES users (id) -- guarantees a user
)
Setting up a database defensively like this can prevent a whole lot of hurt if bugs at the application level arise.
If however, the user
& group
entities share a lot of data (can both own other objects for instance, have profile pages, etc.), a 4 table solution can work out well:
CREATE TABLE users_and_groups (id, ...shared data...
CREATE TABLE users (users_and_groups_id, ...user specific data...
CREATE TABLE groups (users_and_groups_id, .. group specific data...
CREATE TABLE group_members (
group_id,
user_id
FOREIGN KEY (group_id) REFERENCES groups (users_and_groups_id) -- guarantees a group
FOREIGN KEY (user_id) REFERENCES users (users_and_groups_id) -- guarantees a user
)
This has several advantages:
users_and_groups
, and both user
& group
extend that base class/table.Some disadvantages:
type
(or is_group
/ is_user
), determining whether an entity is a group or a user requires a JOIN
, but as this is on primary key on both sides, the overhead should be smallUpvotes: 3
Reputation: 91608
If anything, I think group_member
would be the optional table. You'd only want this table if you needed a many-to-many relationship between users and groups. In other words, if a user can belong to more than one group, you'd want a table that can link a user_id
to a group_id
. If a user can only belong to one group, you'd probably still want a groups
table, and then have a group_id
column on the users
table.
But, to answer your original question, if you stored the group information (such as the group name) in the group_member
table, you'd have to repeat this data for each user within the group. You'd have many rows that have the same group name, and if you wanted to then change a group name later, you'd have to update many rows rather than just one. It also makes it very difficult to tell who's in the same group, and a lot of those sorts of queries would become very inefficient.
Normalizing your distinct groups into a single groups
table is definitely the right approach, regardless of whether you use one or two tables.
Upvotes: 2