我有三个表:
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
关于mysql - 左外连接、WHERE 子句和 COALESCE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30496858/