【问题标题】:SQL query help needed: How to exclude or prioritize rows in SQL in the same table需要 SQL 查询帮助:如何在同一个表中排除或优先考虑 SQL 中的行
【发布时间】:2021-08-10 20:26:19
【问题描述】:

我遇到的问题

我有一个包含用户、角色、客户端和系统的应用程序。 我有一个名为“policies”的表,其中包含我的应用程序依赖的 22 条策略/规则。 22 个中的每一个都可以定义为一个或多个级别。 级别可以是:系统、客户端、角色或用户。 一个系统有 N 个客户端,一个客户端有 N 个角色,一个角色有 N 个用户。 默认情况下,所有 22 条策略都在系统级别定义,但它们可以在任何较低级别被覆盖。

请参阅下表作为示例。为系统定义了 22 个策略 (system_id)。请注意如何在客户端、角色和用户级别(使用相应的 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)

即使 policy_1 是在系统级别设置的,但在客户端级别设置时,重要的是策略的值。在角色级别和用户级别设置时再次发生同样的情况。

查询输入

  • system_id、client_id、role_id、user_id

查询输出 22 项政策设置在最低级别。也就是说,策略应该在它们设置的最低级别上优先考虑。

我尝试过的事情

  • LEFTJOIN 与 NOT INTO 子句的组合

【问题讨论】:

  • 您好,我认为您应该在问题本身中包含 SQL 语句(到目前为止您已经尝试过)。

标签: sql postgresql select left-join exclude-constraint


【解决方案1】:

嗯嗯。 . .如果我理解正确,您可以使用distinct on。关键是过滤和排序:

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
      

【讨论】:

  • 感谢 Gordon,您的回答帮助我找到了我在上面发布的解决方案!
【解决方案2】:

感谢Gordon Linoff的回答,我可以按照他的策略找到一个很好的解决方案(distinct on + order by + case)。这可能不是最优雅或最有效的,但它确实有效。让我知道是否可以进一步改进。

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2011-09-19
    • 2011-04-03
    相关资源
    最近更新 更多