【问题标题】:A double outer join双外连接
【发布时间】:2014-12-04 02:25:16
【问题描述】:

我有一个表格 People、一个表格 Permission 和一个表格 Action。权限用于在人员和操作之间提供多对多关系。

我的目标很简单:我想在 People 中寻找一个人,我想查看 Permission 中列出的权限,以及每个可用的操作,无论此人是否具有权限。

请注意,人员的成员不必在权限中表示。所以,“John”只有在获得写入数据库的权限后才能做某事。

理想情况下,结果应该类似于:

+-------------------------------------------+
+ People.name | Action.name        |Allowed |
+-------------------------------------------+
| John Doe    | Launching missiles | N      |
| John Doe    | Deleting code      | Y      |
+-------------------------------------------+

在我到达那里之前,我只是想用每个数据构建一个简单的查询。 获取某人的权限列表,即使他不在权限表中也很容易:

SELECT * FROM people pp LEFT OUTER JOIN permission pr ON pp.id = pr.people_id 
WHERE pp.name = 'John';

获取权限和操作列表很容易:

SELECT * FROM permission pr LEFT OUTER JOIN action a ON pr.action_id = a.id

但是,我似乎无法执行双外连接来获得我想要的一切:

SELECT * FROM people pp LEFT OUTER JOIN permission pr ON pp.id = pr.permission_id
   LEFT OUTER JOIN people WHERE pp.name = 'John'

向约翰展示了他没有获得许可的事实......但没有任何行动。

换句话说,结果看起来像:

+-----------------------------------------+
+ Name    | People_id | Action_id |Action |
+-----------------------------------------+
| John    |           |           |       |
+-----------------------------------------+

当我想要的时候:

+-----------------------------------------------------------+
+ Name    | People_id | Action_id |Action                   |
+-----------------------------------------------------------+
| John    |           |           | Launching missiles      |
| John    |           |           | Deleting codes          |
| John    |           |           | (every other actions)   |
+-----------------------------------------------------------+

那么,我想要的可能吗?如果是这样,我该如何实现? (我使用的是 PostgreSQL)。

编辑:这是一个 sqlfiddle:http://sqlfiddle.com/#!2/6d502

【问题讨论】:

  • 我有点困惑:“我有一个表格 People,一个表格 Permission 和一个表格 Action。阻止是为了在 People 和 Publication 之间提供多对多的关系。” - 这不应该是“Permission”而不是“Publication”吗?
  • 能否请您发布架构和示例数据?您的查询未加入操作,因此我看不到它如何返回您列出的列标题...SQLFiddle 会很棒。
  • @FrankSchmitt:许可而不是禁止,行动而不是发布。我已经修好了,对不起!我按照 Neville 的建议添加了一个小提琴。

标签: sql postgresql outer-join


【解决方案1】:
SELECT pp.name, pr.id_people, pr.id_action, a.name as action_name
 FROM people pp
 CROSS JOIN action a
 LEFT JOIN permission pr
   ON pr.id_people = pp.id
  AND pr.id_action = a.id

SQLFiddle:http://sqlfiddle.com/#!15/5a7b1/4

按人名过滤添加到查询:

WHERE pp.name = 'John'

【讨论】:

  • 交叉加入!这就是我所缺少的!谢谢!
【解决方案2】:

这应该可行。

SELECT 
    P.name as "people.name", 
    IFNULL(pm.id_people,''), 
    IFNULL(pm.id_action,''), 
    A.name as "action.name"
FROM Action A
CROSS JOIN People P
LEFT JOIN permission pm 
    ON pm.id_action = a.id
    AND pm.id_people = p.id
WHERE p.name = 'John'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-05
    • 2010-12-06
    • 2013-03-13
    • 2017-05-24
    • 2013-12-10
    • 2012-04-03
    • 2019-03-09
    • 1970-01-01
    相关资源
    最近更新 更多