The logic for this type of query starts with generating all combinations of roles and permissions and then removing the ones that exist (using left outer join
).
select p.id as permission_id, p.name as permission_name,
r.id as role_id, r.name as role_name
from roles r cross join
permissions p left outer join
permission_role pr
on pr.permission_id = p.id and
pr.role_id = r.id
where pr.role_id is null;