mySQL从一个表中进行选择,该表在另一个表中不存在,并且不是第三个表中的子表

mySQL从一个表中进行选择,该表在另一个表中不存在,并且不是第三个表中的子表,mysql,yii,rbac,Mysql,Yii,Rbac,我使用Yii-RBAC控制用户对我的应用程序的访问,它由三个mySql表组成 authitem(RBAC角色项) authitemchild(属于其他角色的任何RBAC规则) authitemassignment(为用户分配角色) 例如,我们可能有如下表格: 授权项目: | name (pk) | areaASuperUser areaACreateOnly areaAReadOnly areaAUpdateOnly areaADeleteOnly areaBSuperUs

我使用Yii-RBAC控制用户对我的应用程序的访问,它由三个mySql表组成

authitem
(RBAC角色项)

authitemchild
(属于其他角色的任何RBAC规则)

authitemassignment
(为用户分配角色)

例如,我们可能有如下表格:

授权项目:

|   name (pk)   |
 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly
|   name (pk)   |

 areaABSuperUser

 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly
authitemchild

|   parent (pk)   |   child (pk)   |
 areaASuperUser    areaACreateOnly
 areaASuperUser    areaAReadOnly
 areaASuperUser    areaAUpdateOnly
 areaASuperUser    areaADeleteOnly

 areaBSuperUser    areaBCreateOnly
 areaBSuperUser    areaBReadOnly
 areaBSuperUser    areaBUpdateOnly
 areaBSuperUser    areaBDeleteOnly
|   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
分配

|    itemname (pk)   |   userid (pk)   |
 areaASuperUser       1
|    itemname (pk)   |   userid (pk)   |
 areaABSuperUser      1
在上述场景中,id为1的用户在Area中拥有完整的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*角色都是AreaAsupurer的子角色,所以我不希望它们被返回

任何建议或在正确的方向推动将不胜感激

*编辑:

谢谢@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)   |
 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly
|   name (pk)   |

 areaABSuperUser

 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly
authitemchild

|   parent (pk)   |   child (pk)   |
 areaASuperUser    areaACreateOnly
 areaASuperUser    areaAReadOnly
 areaASuperUser    areaAUpdateOnly
 areaASuperUser    areaADeleteOnly

 areaBSuperUser    areaBCreateOnly
 areaBSuperUser    areaBReadOnly
 areaBSuperUser    areaBUpdateOnly
 areaBSuperUser    areaBDeleteOnly
|   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
分配

|    itemname (pk)   |   userid (pk)   |
 areaASuperUser       1
|    itemname (pk)   |   userid (pk)   |
 areaABSuperUser      1
原来的答案会回来

 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly
因为它过滤掉了父母和孩子,而不是孩子的孩子。我追求的结果(在第二个示例中)是:

***编辑2:

特别针对Yii:


我对Yii做了更多的阅读,并且有很多有用的方法,包括。。。还有一些,这可能有助于抓取我需要的数据

此查询可能会对您有所帮助

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
)

此查询可能对您有所帮助

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表存储类似于树的结构,那么读回存储的项肯定会增加一些复杂性。该节点可以帮助您通过单个查询检索类似于树的结构。谢谢,我熟悉嵌套集模型,在这种情况下可能会更好,但我正在尝试使用Yiis功能,它必须使用这种数据结构,除非我要大量定制它(我想我可能会这样做!),谢谢你的帮助谢谢,这正是我需要做的,我担心如果不使用子选择,就无法获得我需要的结果。第二,你能想出一个办法把孩子从孩子中过滤出来吗?我已经用另一个例子更新了这个问题,我在这里更加不知所措!如果使authitemchild表存储类似于树的结构,那么读回存储的项肯定会增加一些复杂性。该节点可以帮助您通过单个查询检索类似于树的结构。谢谢,我熟悉嵌套集模型,在这种情况下可能会更好,但我正在尝试使用Yiis功能,它必须使用这种数据结构,除非我要大量定制它(我想我可能会这样做!),谢谢你的帮助D