mysql - 左外连接、WHERE 子句和 COALESCE

标签 mysql left-join outer-join

我有三个表:

Users:                  Depts                   Default
| fid | uid | rights |  | fid | did | rights |  | fid | rights |
|-----+-----+--------|  |-----+-----+--------|  |-----+--------|
|  1  |  1  |   4    |  |  1  | 10  |    2   |  |  1  |   2    |
|  3  |  1  |   4    |  |  2  | 10  |    2   |  |  2  |   4    |
+--------------------+  +--------------------+  +--------------+

这些根据用户 ID 和他们所属的部门定义用户对系统中文件的访问权限。访问文件时,有效权限由默认权限(如果有)按顺序确定,默认权限被部门权限(如果有)覆盖,而部门权限又被用户权限(如果有)覆盖。

因此,在这个例子中,用户 1,部门 10 的成员,没有文件 2 的用户权限,但是从他的部门获得了权限级别 2。 (默认权限 4 不适用,因为它们已被部门权限覆盖)

我需要查询这个表结构来确定一个用户对一个或多个文件的有效权限。最初,我唯一的要求是一次获得一个文件的有效权限,我通过为三个子查询中的每一个分配优先级,按优先级顺序将它们与 UNION 组合,然后取只有第一个结果,像这样:

select a.rights from 
    (select 100 as priority, rights from `Users` where `uid`=1 and `fid` = 2 union 
    select 200 as priority, rights from `Depts` where `did`=10 and `fid` = 2 union 
    select 300 as priority, rights from `Default` where `fid` = 2
            ) as a 
            order by priority asc limit 1;

现在,这可能不是特别有效,但到目前为止它一直有效。


我现在的问题是扩展它以检索用户对多个文件的有效权限。由于优先级结构的原因,现有查询无法做到这一点。

我应该能够在三个表中使用FULL OUTER JOIN来生成一组我可以COALESCE的权限值,但是MySQL不支持完全外部连接

在 Stack Overflow 和其他地方进行了一些挖掘之后,我得出了这个(UID、部门 ID 和文件 ID 仅供说明):

select u.fid as fid, u.rights as urights, d.rights as drights, def.rights as defRights 
from 
  (users as u 
    left outer join Depts as d using (fid)
    left outer join Default as def using (fid))  
    where fid in (21, 1823, 1830) and dept_id=10 and uid=1
  union
    select u.fid as fid, u.rights as urights, d.rights as drights, def.rights as defRights 
    from 
      (Depts as d
      left outer join Users as u using (fid)
      left outer join Default as def using (fid))
      where fid in (21, 1823, 1830) and dept_id=10 and uid=1
  union
    select u.fid as fid, u.rights as urights, d.rights as drights, def.rights as defRights 
    from 
      (Default as def 
      left outer join Users as u using (fid)
      left outer join Depts as d using (fid))
      where fid in (21, 1823, 1830) and dept_id=10 and uid=1

从表面上看,这似乎有效,但 WHERE 子句的使用错误地过滤了结果。从我的阅读来看,似乎使用 ON 子句可能是解决方案,但正确的语法让我失败了。

对于我们上面的文件 #2 的示例,我应该期望得到

| fid | Users | Depts | Default |
+-----+-------+-------+---------+
|  2  | null  |   2   |    4    |
+-----+-------+-------+---------+

当合并三个权限值时,这应该给出 2 的有效权限。

此查询可能适用于这个简单的示例。测试中出现的问题是一些应该包含的文件没有包含。


所以,我的问题是:

如何使用 ON 子句而不是 WHERE 来编写查询?

作为奖励,有没有更好的方法可以达到相同的结果?

作为脚注:需要及时审查整个结构,但现在不是时候。这是我必须处理的,直到后来的一些开发提示我们实现更好的东西。

最佳答案

您可以通过将所有您感兴趣的文件合并在一起来创建一个内联 View ,而不是使用 where in。这将维护查询链的外部结束

例如:

select files.fid, u.rights, d.rights, def.rights
  from (
    select 1 as fid
    union all
    select 2 as fid
    union all
    select 3 as fid
    -- all the files you are interested in
  ) files
  left join users u
    on files.fid = u.fid
      and u.uid = 2         -- put the user you are searching for here
  left join depts d
    on files.fid = d.fid
      and d.did = 10        -- put the dept you are searching for here
  left join `default` def
    on files.fid = def.fid

quick demo here

关于mysql - 左外连接、WHERE 子句和 COALESCE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30496858/

相关文章:

mysql - having 子句中的 Magento 未知列

sql-server - 直接或通过中介将第三个表与第一个表连接

MySQL JOIN 使用三张表

mysql - 与供应商表和供应商评级表进行左连接时,仅显示一条记录

Mysql 三表连接结果空集

mysql - rails : retrieve data from multiple tables without association

Mysql 错误 1136 Excel

php - 这个登录脚本是否良好/当前/安全?

如果子查询为空,MySQL 问题

mysql - LEFT OUTER JOIN 没有显示所有行?