Search code examples
mysqljoinleft-joincross-join

mySql N to N double join with null - CROSS join from answer


I have two tables one called permissions and one called roles which are related through a third table called RolePermissions in a N-N relationship.

Permissions
 id <- PK
 name


Roles
 id <- PK
 name

RolePermisions
 RoleId  <-PK
 PermissionId <-PK
 isAllowed

What I want is to get the full list of permissions of a specific role, and NULLs when there isn't a value in the RolePermission table for that Role. Left joins usually do the trick, but I can't work this one out.

Basically let's say I have the following values:

In Permsission:

1 - Per1
2 - Per2
3 - Per3

And in Roles:

1 - Role1
2 - Role2

And in RolePermissions:

RoleId  -  PermissionId - isAllowed
 1            1             true
 1            2             false
 1            3             true
 2            1             true

The following query sorta works but it will not return NULLs for those values not in RolePermissions:

select permissions.name, rolepermissions.allowed 
FROM permissions LEFT JOIN rolepermissions  
    ON rolepermissions.permissionId = permissions.id 
WHERE rolepermissions.roleId = 2;

The result I would be looking for when querying for Role 2 is

Per1 - true
Per2 - NULL
Per3 - NULL

Solution

  • You can do this with a CROSS JOIN:

    SELECT
        r.ID AS RoleID,
        p.ID AS PermissionID,
        rp.IsAllowed
    FROM
        Roles r CROSS JOIN
        Permissions p LEFT JOIN
        RolePermissions rp ON rp.RoleId = r.ID AND rp.PermissionID = p.ID
    WHERE r.ID = @RoleID