到目前为止,我所看到的一切都是关于自动删除数据库中的重复条目。我想在开头强调数据库中没有重复数据。我还要从这样一个事实开始:我仍然在学习RDBMS设计,规范化,关系,最重要的是SQL!
我有一个客户端表,包含clientid(PK)和client_name。我有一个角色表,有一个roleid(PK)和一个role_name。任何客户端都可以拥有与之关联的多个角色。所以我创建了一个client_role_link表,clientid和roleid作为两个字段。然后我运行这个:
SELECT client.client_name, role.role_name FROM client
LEFT JOIN client_role_link ON client_role_link.clientid=client.clientid
LEFT JOIN role ON client_role_link.roleid=role.roleid
WHERE (role.roleid='1' OR role.roleid='2')
所以假设我有一个客户端,它有两个与之关联的角色(角色'1'和'2')。此查询返回两行,每个角色一行。当我得到这些结果时,我正在使用while
循环来循环结果并将它们输出到<select>
列表中。然后它会导致两个<option>
列出相同的客户端。
我理解为什么我的查询返回两行,这是有道理的。所以这里有两个问题:
思想?
答案 0 :(得分:3)
如果您想同时显示这两个角色,那么您的查询就是OK
。
MySQL
不支持数组数据类型,因此您应该使用带有重复客户端名称的结果集在PHP
端填充关联数组。
如果您只需要显示具有其中任一角色的客户,请使用此查询:
SELECT c.*
FROM client c
WHERE c.clientid IN
(
SELECT roleid
FROM client_role_link crl
WHERE crl.roleid IN (1, 2)
)
这将为每个客户返回一条记录,但不会显示任何角色。
第三种方法会破坏服务器端的角色名称:
SELECT c.*, GROUP_CONCAT(role_name SEPARATOR ';') AS roles
FROM client c
LEFT JOIN
client_role_link crl
ON crl.clientid = c.clientid
AND crl.roleid IN (1, 2)
LEFT JOIN
role r
ON r.roleid = crl.roleid
GROUP BY
c.id
并在PHP
方面展开它们,但请确保角色名称不会与分隔符混在一起。
答案 1 :(得分:0)
您可以使用mysql_fetch_assoc()以阵列形式返回它们。那么你可能会有类似代码未经测试的东西,但可以正常工作:
$sql = "SELECT client.id, client.client_name, role.role_name FROM client LEFT JOIN client_role_link ON client_role_link.clientid=client.clientid LEFT JOIN role ON client_role_link.roleid=role.roleid WHERE (role.roleid='1' OR role.roleid='2')";
$result = mysql_query($sql);
$res = array();
while ($row = mysql_fetch_assoc($result)) {
$res[$row['id']]['roles'][] = $row['role_name'];
$res[$row['id']]['client_name'] = $row['client_name']; //you'll be overwriting each iteration probably a better way
}