Reputation: 33
I'm working on a web app with mysql involving a user role table where permission levels are stored as well as role ids and associated to usernames and their ids (redundancy to continue supporting legacy code).
I want to be able to display every user's role as a comma seperated list in plain English with minimal hit to the DB (>1k users) as well as their permission level.
Permissions are stored as bits in the ismanager and ishead columns and roleids are keyed to define_roles (id, rolename)
Here's what I've got works (but doesn't show user levels)
<?
$rolenames = array();
foreach($db->query("SELECT id, rolename FROM define_roles") as $row)
{
$rolenames[$row['id']] = $row['rolename'];
}
foreach($db->query("SELECT DISTINCT userid, username,
GROUP_CONCAT(DISTINCT roleid ORDER BY roleid) AS idlist
FROM user_roles
GROUP BY userid
ORDER BY username ASC") as $row)
{
$rolestring = '';
//echo $row['idlist'];
foreach(explode(',',$row['idlist']) as $id)
{
$rolestring .= " ".$rolenames[$id].",";
}
$rolestring = rtrim($rolestring,',');
echo "<tbody>
<tr>
<td><font size='1'>" . $row['username'] . "</font></td>
<td><font size='1'>" .$rolestring. "</font></td>
</tr>";
}
?>
Output:
What I want to see is
The best I could come up with (though it doesn't work) is:
$rolenames = array();
foreach($db->query("SELECT id, rolename FROM define_roles") as $row)
{
$rolenames[$row['id']] = $row['rolename'];
$rolenames[$row['id']."10"] = $row['rolename']." (Manager)";
$rolenames[$row['id']."01"] = $row['rolename']." (Head)";
$rolenames[$row['id']."11"] = $row['rolename']." (Head)";
}
foreach($db->query("SELECT DISTINCT userid, username,
GROUP_CONCAT
(
CONCAT(roleid,ismanager,ishead) ORDER BY roleid
) AS idlist
FROM user_roles
GROUP BY userid
ORDER BY username ASC") as $row)
Upvotes: 3
Views: 563
Reputation: 284
Firstly, you should probably normalize your database so that you have a separate table linking the users and defined roles. But that's a separate thing and I appreciate you may not be able to do that.
If I've understood what's in your tables correctly, the answer is this, I think:
SELECT
userid,
username,
GROUP_CONCAT(DISTINCT
CONCAT(
(SELECT d.rolename FROM define_roles AS d
WHERE d.id = roleid)
),
IF(ismanager = 1, " (Manager)", ""),
IF(ishead = 1, " (Head)", "")
) AS roles
FROM user_roles
GROUP BY userid;
You won't need the initial sql where you looked up the rolenames from define_roles.
[EDIT]: Sorry, updated with brackets around the inner SELECT.
Upvotes: 2