mySQL 从一个表中选择,该表在另一个表中不存在,并且不是第三个表中的子表
Posted
技术标签:
【中文标题】mySQL 从一个表中选择,该表在另一个表中不存在,并且不是第三个表中的子表【英文标题】:mySQL select from one table where does not exists in another, and is not a child in a third table 【发布时间】:2012-09-18 09:16:22 【问题描述】:我正在使用 Yii RBAC 来控制用户对我的应用程序的访问,它由三个 mysql 表组成;
authitem
(RBAC 角色项)
authitemchild
(属于其他角色的任何 RBAC 规则)
authitemassignment
(为用户分配角色)
例如,我们可能有这样的表格:
认证项目:
| name (pk) |
areaASuperUser
areaACreateOnly
areaAReadOnly
areaAUpdateOnly
areaADeleteOnly
areaBSuperUser
areaBCreateOnly
areaBReadOnly
areaBUpdateOnly
areaBDeleteOnly
authitemchild
| parent (pk) | child (pk) |
areaASuperUser areaACreateOnly
areaASuperUser areaAReadOnly
areaASuperUser areaAUpdateOnly
areaASuperUser areaADeleteOnly
areaBSuperUser areaBCreateOnly
areaBSuperUser areaBReadOnly
areaBSuperUser areaBUpdateOnly
areaBSuperUser areaBDeleteOnly
auithitemassignment
| itemname (pk) | userid (pk) |
areaASuperUser 1
在上述场景中,id 为 1 的用户在 areaA 中具有完整的 CRUD 访问权限。我需要的是用户也没有有权访问的所有角色的列表,我还需要考虑他们也有权访问的任何角色的子级。
我可以轻松获取用户无权访问的所有角色:
SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `authassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE `aa`.`itemname` IS NULL
但这会返回:
| name |
areaACreateOnly
areaAReadOnly
areaAUpdateOnly
areaADeleteOnly
areaBSuperUser
areaBCreateOnly
areaBReadOnly
areaBUpdateOnly
areaBDeleteOnly
因为所有 areaA* 角色都是 areaASuperUser 的子角色,所以我不希望它们返回。
任何建议或朝着正确方向的推动将不胜感激!
* 编辑:
感谢@SuVeRa,您的回答:
SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `authassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE
`aa`.`itemname` IS NULL
AND `ai`.`name` NOT IN (
SELECT
`aic`.`child` itemname
FROM `authitemchild` `aic`
JOIN `authassignment` `aa`
ON `aa`.`itemname` = `aic`.`parent`
WHERE `aa`.`userid` = 1
)
非常适合上面的示例,但是我刚刚扩展了应用程序以包含多个儿童级别,即
认证项目:
| name (pk) |
areaABSuperUser
areaASuperUser
areaACreateOnly
areaAReadOnly
areaAUpdateOnly
areaADeleteOnly
areaBSuperUser
areaBCreateOnly
areaBReadOnly
areaBUpdateOnly
areaBDeleteOnly
areaCSuperUser
areaCCreateOnly
areaCReadOnly
areaCUpdateOnly
areaCDeleteOnly
authitemchild
| parent (pk) | child (pk) |
areaABSuperUser areaASuperUser
areaABSuperUser areaBSuperUser
areaASuperUser areaACreateOnly
areaASuperUser areaAReadOnly
areaASuperUser areaAUpdateOnly
areaASuperUser areaADeleteOnly
areaBSuperUser areaBCreateOnly
areaBSuperUser areaBReadOnly
areaBSuperUser areaBUpdateOnly
areaBSuperUser areaBDeleteOnly
areaCSuperUser areaCCreateOnly
areaCSuperUser areaCReadOnly
areaCSuperUser areaCUpdateOnly
areaCSuperUser areaCDeleteOnly
auithitemassignment
| itemname (pk) | userid (pk) |
areaABSuperUser 1
原来的答案会返回;
| name |
areaACreateOnly
areaAReadOnly
areaAUpdateOnly
areaADeleteOnly
areaBCreateOnly
areaBReadOnly
areaBUpdateOnly
areaBDeleteOnly
areaCSuperUser
areaCCreateOnly
areaCReadOnly
areaCUpdateOnly
areaCDeleteOnly
因为它过滤掉了父母和孩子,而不是孩子的孩子。我追求的结果(在第二个例子中)是:
| name |
areaCSuperUser
areaCCreateOnly
areaCReadOnly
areaCUpdateOnly
areaCDeleteOnly
***编辑2:
专门针对 Yii:
我对 Yii 做了更多阅读,CAuthManager 有许多有用的方法,包括 hasItemChild()、isAssigned()、getItemChildren(),... 等等,它们可以帮助抓取数据,例如我需要
【问题讨论】:
【参考方案1】:此查询可能对您有所帮助
SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `auithitemassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE
`aa`.`itemname` IS NULL
AND `ai`.`name` NOT IN (
SELECT
`aic`.`child` itemname
FROM `authitemchild` `aic`
JOIN `auithitemassignment` `aa`
ON `aa`.`itemname` = `aic`.`parent`
WHERE `aa`.`userid` = 1
)
【讨论】:
谢谢,这正是我需要做的,我担心不使用子选择就无法获得我需要的结果。其次,你能想出一种方法来过滤掉孩子的孩子吗?我已经用另一个例子更新了这个问题,我在这里更加茫然! 您正在制作 authitemchild 表来存储 TREE 有点像结构,读回存储的项目肯定会增加一些复杂性。该节点可以帮助您如何通过单个查询检索树种结构。 link 谢谢,我熟悉嵌套集模型,对于这种情况可能会更好,但我正在尝试使用必须使用此数据结构的 Yiis RBAC 功能,除非我将对其进行大量定制(我想我可能会这样做!)感谢您的帮助! :D以上是关于mySQL 从一个表中选择,该表在另一个表中不存在,并且不是第三个表中的子表的主要内容,如果未能解决你的问题,请参考以下文章