显示每个父母的所有孩子

Chr*_* G. 12 html php mysql

我有一张桌子People.我希望显示一个由每个父项组成的HTML表,其中所有子项都直接位于它们之下.

 _________
|People   |_____________________________________________
|-------------------------------------------------------|
| id     | parent | firstname     | lastname            |
|-------------------------------------------------------|
| 1        0        James           Donovan             |
| 2        0        Jeffrey         Williams            |
| 3        0        Emmit           Herring             |
| 4        2        Carol           Williams            |
| 5        2        Sarah           Williams            |
| 6        1        Nikolai         Donovan             | 
|_______________________________________________________|
Run Code Online (Sandbox Code Playgroud)

预期产量:

 ________________________________________________
|Jeffrey Williams                                |
|------------------------------------------------|
|  - Carol Williams                              |
|  - Sarah Williams                              |
|________________________________________________|
|James Donovan                                   |
|------------------------------------------------|
|  - Nikolai Donovan                             |
|________________________________________________|
|Emmit Herring                                   |
|------------------------------------------------|
|________________________________________________|
Run Code Online (Sandbox Code Playgroud)

如何构建包含正确迭代结果集的关联数组?我对正确的SQL和正确的PHP构建最终数组感到困惑.

具体来说,我不确定如何在两个MySQL表之间显示层次关系.据我所知,SQL结果集不是多维的.将SQL查询放在for循环中对性能来说太糟糕了.所以你会怎么做?

我想我正在寻找MySQL中的邻接列表实现.

如果我可以将所有内容分成两个表,这个问题应该很容易,但不幸的是我必须坚持使用这种非正常的表结构.

Ilm*_*nen 13

有几种方法可以做到:

1.显而易见的是首先获取所有父项的列表,然后在循环中为每个父项的子项运行单独的查询.你说这对于"性能很糟糕",但它确实不应该,假设你的parent列上有一个索引,而你的MySQL服务器不在地球的另一边.


2.如果你真的想要这样做是在一个查询中,你可以使用LEFT JOIN表格对自己:

SELECT
  p.id AS parent_id,
  p.firstname AS parent_firstname,
  p.lastname  AS parent_lastname,
  c.id AS child_id,
  c.firstname AS child_firstname,
  c.lastname  AS child_lastname
FROM
  People AS p
  LEFT JOIN People AS c ON c.parent = p.id
WHERE p.parent = 0
ORDER BY p.id
Run Code Online (Sandbox Code Playgroud)

同样,你真的,真的需要在一个索引parent列.该ORDER BY条款旨在确保每个父母的子女一起分类; 您可以将其更改为例如p.lastname, p.firstname, p.id, c.lastname, c.firstname, c.id您希望按字母顺序排序的名称.在PHP中,您需要循环结果并在父ID更改时打印新标头(并记住处理child_*列为NULL的情况),如下所示:

$res = mysql_query( $sql );
$last_parent_id = 0;
while ( $row = mysql_fetch_object( $res ) ) {
    if ( $row->parent_id != $last_parent_id ) {
        // print parent header
        $last_parent_id = $row->parent_id;
    }
    if ( $row->child_id ) {
        // print child row
    }
}
Run Code Online (Sandbox Code Playgroud)

3.第三个选项是使用简单SELECT * FROM People查询获取所有行,并在PHP中构建树:

$res = mysql_query( "SELECT * FROM People" );  // add WHERE clauses if needed
$names = array();
$parents = array();
$children = array();

while ( $row = mysql_fetch_object( $res ) ) {
    $names[ $row->id ] = array( $row->firstname, $row->lastname );
    if ( $row->parent == 0 ) {
        $parents[] = $row->id;
    } else {
        if ( !array_key_exists( $row->parent, $children ) )
            $children[ $row->parent ] = array();
        $children[ $row->parent ][] = $row->id;
    }
}

foreach ( $parents as $parent_id ) {
    // print parent header
    if ( array_key_exists( $parent_id, $children ) ) {
        foreach ( $children[ $parent_id ] as $child_id ) {
            // print child row
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

PS.如果您实际上并不想显示表中的所有父项和子项,而只是表示属于单个族的那些父项和子项,那么您仍应尝试在SQL中进行过滤以避免获取太多记录.