MySQL多个LEFT JOIN返回重复的行

时间:2018-07-07 15:08:39

标签: php mysql duplicates left-join

我有一个MySQL查询,该查询多次使用LEFT JOIN来连接author相同的不同表。但是,当我echo得出结果时,如果我在32,920表中只记录了4行,而在其他三行中记录了约100行,则会给我返回大量重复行(实际上是grouppost) 。

status

+----+------+--------------+--------+------+-------+---------------------+
| id | osid | account_name | author | type | data  |      postdate       |
+----+------+--------------+--------+------+-------+---------------------+
|  1 |    1 | John         | John   | a    | lkjg. | 2018-01-01 00:00:00 |
+----+------+--------------+--------+------+-------+---------------------+

article_status

+----+------+--------------+--------+------+-------+------+---------------------+
| id | osid | account_name | author | type | data  | artid |      postdate       |
+----+------+--------------+--------+------+-------+------+---------------------+
|  2 |    1 | John         | John   | a    | bcda. |    1 | 2018-01-01 00:00:00 |
+----+------+--------------+--------+------+-------+------+---------------------+

grouppost

+----+-----+--------+--------+------+-------+----------------------+
| id | pid | gname  | author | type | data  |         pdate        |
+----+-----+--------+--------+------+-------+----------------------+
|  3 |   1 | Group1 | John   |    1 | ABCD. |  2018-01-01 00:00:00 |
+----+-----+--------+--------+------+-------+----------------------+

photos_status

+----+------+--------------+--------+------+-------+------+---------------------+
| id | osid | account_name | author | type | data  | photo |      postdate       |
+----+------+--------------+--------+------+-------+------+---------------------+
|  4 |    1 | John         | John   | a    | abcd. | a.jpg | 2018-01-01 00:00:00 |
+----+------+--------------+--------+------+-------+------+---------------------+

预期结果是将四行连接在一起,并从中获得具有指定名称的id

+---------+--------+-------+-------+
| stat_id | art_id | gr_id | ph_id |
+---------+--------+-------+-------+
|       1 |      2 |     3 |   4   |
+---------+--------+-------+-------+

MySQL查询:

$sql = "
SELECT a.id AS art_id
     , g.id AS gr_id
     , p.id AS ph_id
     , s.id AS stat_id 
  FROM article_status AS a 
  LEFT 
  JOIN grouppost AS g 
    ON a.author = g.author 
  LEFT 
  JOIN photos_status AS p 
    ON a.author = p.author 
  LEFT 
  JOIN status AS s 
    ON a.author = s.author 
   AND a.author = 'John' 
   AND g.author = 'John' 
   AND p.author = 'John' 
   AND s.author = 'John'
";

$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {
    echo $row["gr_id"]."<br>"; // returns back duplicate rows
}
$stmt->close();
mysqli_close($conn);

寻求可能的错误:

var_dump($ result): object(mysqli_result)#3 (5) { ["current_field"]=> int(0) ["field_count"]=> int(4) ["lengths"]=> NULL ["num_rows"]=> int(32920) ["type"]=> int(0) }

与上面的var_dump一样,["field_count"]=> int(4)是正确的,因为在查询中有4个字段受影响。但是,["num_rows"]=> int(32920)会返回32,920,这是完全错误的。

var_dump($ stmt): object(mysqli_stmt)#2 (10) { ["affected_rows"]=> int(0) ["insert_id"]=> int(0) ["num_rows"]=> int(0) ["param_count"]=> int(0) ["field_count"]=> int(4) ["errno"]=> int(0) ["error"]=> string(0) "" ["error_list"]=> array(0) { } ["sqlstate"]=> string(5) "00000" ["id"]=> int(1) }

同样,我想从article_status相同的grouppostphotos_statusstatusauthor表中选择所有受影响的行,例如在示例中为John

1 个答案:

答案 0 :(得分:2)

首先,您的查询应简化为以下内容。

SELECT 
      a.id art_id, 
      g.id gr_id, 
      p.id ph_id, 
      s.id stat_id
   FROM 
      article_status a 
         LEFT JOIN grouppost g 
            ON a.author = g.author 
         LEFT JOIN photos_status p 
            ON a.author = p.author 
         LEFT JOIN status s 
            ON a.author = s.author 
   where
      a.author = 'John' 

您已为每个其他联接显式重新添加AND author ='John'。他们应该保留各自的“ ON”子句,而不是最后分组。另外,通过传递关联,例如:

A = B   and B = C, therefore A = C.

如果您已经在每个表之间加入了AUTHOR,那么为“ a.author ='John'”拥有一个WHERE子句也将所有其余的都捕获为'John'。

对于重复项,可能是基于笛卡尔结果,即您作为作者有多个“约翰”记录,并且正在根据名称而不是您想获得的名称与其他所有ID联接。 / p>

Ex数据。

Article Status
id author author_lastName
1  John   A
2  Bill   E
3  John   H
4  Mary   J
5  John   M


GroupPost
id  author  author_lastname
1   Mary    J
2   John    M
3   John    M
4   John    A
5   Bill    E
6   John    H

因此,仅从上述两个表的示例中,对于Article表中的每个“ John”,它都会在GroupPost表中找到所有“ John”名称,并得出

Article ID   GroupPostIT
1 (John A)   2 (John M)
1 (John A)   3 (John M)
1 (John A)   4 (John A)
1 (John A)   6 (John H)

3 (John H)   2 (John M)
3 (John H)   3 (John M)
3 (John H)   4 (John A)
3 (John H)   6 (John H)

6 (John M)   2 (John M)
6 (John M)   3 (John M)
6 (John M)   4 (John A)
6 (John M)   6 (John H)

现在,将其也带到其他表中,您会发现您获得的收益超出了预期。与通用名称相比,表之间可能需要更好的“ ID”关联。

例如,您的GroupPost应该具有authorID,而不仅仅是名称...与其他表相同。