Un'opzione, altamente normalizzata, è rendere le tabelle più simili
create table notifications(
notification_id serial primary key,
date_created timestamp not null default now(),
title_id text not null,
message_id text not null,
icon text not null default 'logo'
);
create table usernotifications
(
notification_id integer references notifications,
user_id integer references users
);
create table groupnotifications
(
notification_id integer references notifications,
group_id integer references groups
);
create table companynotifications
(
notification_id integer references notifications,
company_id integer references companies
);
dove le voci esistono solo nella tabella delle notifiche (utente/azienda/gruppo) pertinente per una determinata notifica.
(Non credo che ci sia qualcosa di sbagliato nelle chiavi esterne nullable nella situazione in cui ciò indica che la chiave esterna è facoltativa, ma più chiavi esterne di tipo simile danno l'impressione di un design denormalizzato)