Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 导致返回重复行的一对多链接表_Php_Mysql_Relationship - Fatal编程技术网

Php 导致返回重复行的一对多链接表

Php 导致返回重复行的一对多链接表,php,mysql,relationship,Php,Mysql,Relationship,到目前为止,我所看到的一切都是关于自动删除数据库中的重复条目。我想在开始时强调,数据库中没有重复数据。我还将从以下事实开始:我仍然在学习RDBMS设计、规范化、关系,最重要的是SQL 我有一个客户表,有一个clientid(PK)和一个client_名称。我有一个角色表,有一个roleid(PK)和一个role_名称。任何客户端都可以有多个与其关联的角色。因此,我创建了一个client_role_link表,其中clientid和roleid是两个字段。然后我运行这个: SELECT clien

到目前为止,我所看到的一切都是关于自动删除数据库中的重复条目。我想在开始时强调,数据库中没有重复数据。我还将从以下事实开始:我仍然在学习RDBMS设计、规范化、关系,最重要的是SQL

我有一个客户表,有一个clientid(PK)和一个client_名称。我有一个角色表,有一个roleid(PK)和一个role_名称。任何客户端都可以有多个与其关联的角色。因此,我创建了一个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
循环遍历结果并将它们输出到
列表中。然后,它会对列出的同一个客户端导致两个

我理解为什么我的查询返回两行,这是有道理的。所以这里有两个问题:

  • 我应该使用更好的数据库/表设计,还是更优化的查询
  • 或者这是我应该在PHP中处理的事情?如果是这样,有没有更优雅的解决方案,将所有结果添加到一个数组中,然后在数组中循环并删除重复项

  • 想法?

    如果您想同时显示这两个角色,那么您的查询是
    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的
    端分解它们,但要确保角色名不会与分隔符混合。

    您可以使用它们以数组形式返回。然后,您可以有一些未经测试的代码,但可以工作:


    你们到底想用它来完成什么?您想输出所有客户端的列表还是所有角色的列表?还是别的什么?我只想显示具有特定角色的客户机,并让它们可以选择。在这个特殊的例子中,我实际上不需要拉角色名。我认为第一个例子更符合我的要求,但我对“in”不太熟悉,所以我必须查一下。我假设您只是针对生成的数据集运行SQL?是的,我知道MySQL没有数组,我正在使用mysqli和fetch_assoc()方法将我的数据从结果集中获取到PHP数组中。我只是不想在生成的数组中循环并删除重复项!这部分是我试图避免的,但比我提出的解决方案要干净得多。
    $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
    }