PROBLEM I HAVE
I have an application with Users, Roles, Clients and Systems. I have a table named 'policies' that contains the 22 policies/rules my application relies on. Each one of the 22 can be defined at one or more levels. The levels can be: System, Client, Role or User. A system has N clients, a client has N roles and a role has N users. By default, all 22 policies are defined at the System level, but they can be OVERWRITTEN at any lower level.
See the table below as an example. There are 22 policies defined for the system (system_id). Notice how the policy_1 is also set at the client, role and user level (with the corresponding id's).
name | value | level
-----------------------------+----------+--------------------------------------
policy_1 | 1 | system_id
policy_2 | 4 | system_id
policy_3 | 6 | system_id
[policies 4 to 21] | ... | ...
policy_22 | 9 | role_id
policy_1 | 2 | client_id
policy_1 | 9 | role_id
policy_1 | 7 | user_id
(22 rows)
Even though the policy_1 is set at the System level, when setting it at the Client level, that's the policy's value that matters. Same happening again when setting it at Role level, and again at User level.
QUERY INPUT
- system_id, client_id, role_id, user_id
QUERY OUTPUT The 22 policies set at the LOWEST level. That is, the policies should be prioritized on the lowest level they are set.
THINGS I'VE TRIED
- A combination of LEFTJOINs with NOT INTO clauses
Thanks to the answer from Gordon Linoff, I could find a good solution following his strategy (
distinct on
+order by
+case
). This may not be the most elegant or efficient but it works. Let me know if it can be improved further.