My application has notification settings for users that can belong to groups. A group administrator can define settings for the entire group, so that when any user performs an action, the administrator is notified. The administrator can also define settings for an individual user, which will override the group setting.
Right now I have a database with columns: group_id, action1, action2, action3, ...
. The actions are booleans that determine if the administrator is notified when that action is performed by a user in his or her group.
I could make a separate table owned by the User model instead of the Group model, but it feels inefficient to store the exact same data in an entirely separate table save changing the group_id
to user_id
.
Another option is to add user_id
to the table I already have, and allow null values for group_id
. When determining notification settings for a User, the application would first choose the setting based on User, and fallback to the setting where group_id
is not null. This feels inefficient because there will be many null values in the database, but it definitely requires less work on my part.
Is there a design for this situation that is more efficient than the two I've described?
Each table should include a column or set of columns that uniquely identifies each row stored in the table. This is often a unique identification number, such as an employee ID number or a serial number. In database terminology, this information is called the primary key of the table.
A one-to-many relationship is the most common type of relationship. In a one-to-many relationship, a record in Table A can have many matching records in Table B, but a record in Table B has only one matching record in Table A.
Generally, there are two strategies to handle a situation like this:
Essentially, each of the possible parent tables will have its own, separate foreign key in the child table, and there is a CHECK enforcing exactly one of them is non-NULL. Since FKs are only enforced on non-NULL fields (meaning, when a FK is set to NULL there is no database-level validation), only one of the FKs will be enforced.
For example:
(relationship between user and group omitted)
CHECK (
(group_id IS NOT NULL AND user_id IS NULL)
OR (group_id IS NULL AND user_id IS NOT NULL)
)
Inherit user and group from a common supertype and then connect the setting to the supertype:
For more information on inheritance (aka. category, subclassing, subtype, generalization hierarchy etc.), take a look at "Subtype Relationships" chapter of ERwin Methods Guide. Unfortunately, modern DBMSes don't natively support inheritance - for some ideas about physically implementing it, take a look at this post.
This is a heavy-duty solution probably not justified for just two tables (groups and users), but can be quite "scalable" for many tables.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With