I'm using Yii RBAC to control user access to my app, it consists of three mySql tables;
authitem (the RBAC role items)
authitemchild (any RBAC rules that belong to other roles)
authitemassignment (assigning roles to a user)
For example we may have tables like so:
authitem:
|   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
In the above scenario, user with id of 1 has complete CRUD access in areaA. What I need is a list of all the roles the user does not have access too, and I need to take into account the children of any roles they have access too as well.
I can easily grab all the roles the user doesn't have access to:
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
But this returns:
 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly
 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly
And because all the areaA* roles are children of areaASuperUser, I don't want them returned.
Any advice or a push in the right direction would be greatly appreciated!
* Edit:
Thanks @SuVeRa, your answer:
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
)
works perfectly for the example above, however I've just extended the app to include more than one level for children, i.e.
authitem:
|   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
The original answer would return;
 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly
 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly
As it's filtering out the parent and child, but not the children of children. The result I'm after (in this second example) is:
 |   name    |
 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly
***Edit 2:
Specifically for Yii:
I've done some more reading into Yii, and CAuthManager has a number of helpful methods, including hasItemChild(), isAssigned(), getItemChildren(), ... and others, that could help with grabbing data like I need
 
    