简体   繁体   English

SQL 需要查询帮助:如何在同一个表中排除或优先考虑 SQL 中的行

[英]SQL query help needed: How to exclude or prioritize rows in SQL in the same table

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.我有一个名为“policies”的表,其中包含我的应用程序依赖的 22 条策略/规则。 Each one of the 22 can be defined at one or more levels. 22 个中的每一个都可以定义为一个或多个级别。 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.一个系统有 N 个客户端,一个客户端有 N 个角色,一个角色有 N 个用户。 By default, all 22 policies are defined at the System level, but they can be OVERWRITTEN at any lower level.默认情况下,所有 22 个策略都在系统级别定义,但它们可以在任何较低级别被覆盖。

See the table below as an example.请参阅下表作为示例。 There are 22 policies defined for the system (system_id).为系统定义了 22 个策略 (system_id)。 Notice how the policy_1 is also set at the client, role and user level (with the corresponding id's).请注意如何在客户端、角色和用户级别(使用相应的 id)设置 policy_1。


            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.即使 policy_1 是在系统级别设置的,但在客户端级别进行设置时,重要的是策略的值。 Same happening again when setting it at Role level, and again at User level.在角色级别和用户级别设置时再次发生同样的情况。

QUERY INPUT查询输入

  • system_id, client_id, role_id, user_id system_id、client_id、role_id、user_id

QUERY OUTPUT The 22 policies set at the LOWEST level. QUERY OUTPUT在最低级别设置的 22 条策略。 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 LEFTJOIN 与 NOT INTO 子句的组合

Hmmmm.嗯。 . . . . If I understand correctly you can use distinct on .如果我理解正确,您可以distinct on . The key is filtering and ordering:关键是过滤和排序:

select distinct on (name) p.*
from policies p
where level = 'system_id' and value = $system_id or
      level = 'client_id' and value = $client_id or
      level = 'role_id' and value = $role_id or
      level = 'user_id' and value = $user_id
order by p.name,
         (case when level when 'system_id' then 1 when 'client_id' then 2 when 'role_id' then 3 when 'user_id' then 4 end) desc
      

Thanks to the answer from Gordon Linoff , I could find a good solution following his strategy ( distinct on + order by + case ).感谢Gordon Linoff的回答,我可以按照他的策略找到一个很好的解决方案( 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.让我知道它是否可以进一步改进。

select distinct on (name) *
from policies
where level = $system_id  or
      level = $client_id or
      level = $role_id  or
      level = $user_id
order by name,
         (case when level = $system_id then 1 when level = $client_id then 2 when level = $role_id then 3 when level = $user_id then 4 end) desc;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM