2011-11-01 56 views
12

我有一张表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    | 
|_______________________________________________________| 

预期输出:

________________________________________________ 
|Jeffrey Williams        | 
|------------------------------------------------| 
| - Carol Williams        | 
| - Sarah Williams        | 
|________________________________________________| 
|James Donovan         | 
|------------------------------------------------| 
| - Nikolai Donovan        | 
|________________________________________________| 
|Emmit Herring         | 
|------------------------------------------------| 
|________________________________________________| 

如何建立一个包含正确的结果集遍历关联数组?我对正确的SQL和正确的PHP构建最终数组感到困惑。

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

我想我正在寻找一个在MySQL中的邻接表实现。

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

+0

你可以使用jquery吗? – defau1t

+0

为什么我必须使用jQuery来显示每个父项的子项一样简单的内容?这里没有PHP解决方案吗? –

+0

@Mark我想我的问题还不够清楚。我不是为了帮助家庭作业。我更新了这个问题。 –

回答

13

有几种方法可以做到这一点:

最明显的一个是先获取所有家长的名单,然后运行每个家长在孩子们一个单独的查询循环。你说这对于性能来说是“糟糕的”,但它确实不应该是这样的,假设你有一个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 

同样,你真的,真的需要parent列的索引。 ORDER BY条款是为了确保每个父母的孩子一起排序;你可以改变它,例如如p.lastname, p.firstname, p.id, c.lastname, c.firstname, c.id如果你想按字母顺序排序的名称。在PHP中,你则需要循环的结果并打印新的头每当父ID的变化(记住处理,其中child_*列是空的情况下)喜欢的东西:

$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 
    } 
} 

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 
     } 
    } 
} 

诗篇。如果您实际上不想在表中显示父母和子女,但只是属于一个家庭的父母和子女,那么您仍然应该尝试在SQL中进行过滤以避免获取太多记录。

0

为什么不在JavaScript中创建多线阵列?之后,只需循环访问数组即可在DOM中获得结果。

+1

因为网站用户不应该被要求启用Javascript。为什么不显示父 - >子关系列表而不诉诸用JavaScript来操纵DOM?我使用PHP和MySQL。 –

1

你可以在一个循环中使用一个循环:

$res = mysql_query("SELECT PARENT"); 
while($row = mysql_fetch_assoc($res)) 
{ 

    // echo parent 

    $res2 = mysql_query("SELECT CHILD WHERE PARENT SOMETHING"); 
    while($row2 = mysql_fetch_assoc($res2)) 
    { 

    // echo child 
    } 
} 

或者,保持它后,并存储一个标志。

$people = array(); 

$res = mysql_query("SELECT PARENT"); 
while($row = mysql_fetch_assoc($res)) 
{ 
    $people[] = array('is_parent' => true, 
        'info'  => $row); 

    $res2 = mysql_query("SELECT CHILD WHERE PARENT SOMETHING"); 
    while($row2 = mysql_fetch_assoc($res2)) 
    {  
    $people[] = array('is_parent' => false, 
         'info'  => $row2); 
    } 
} 

// later 

foreach($people as $person) 
{ 
    if($person['is_parent']) 
    { 
    // echo parent 
    } 
    else 
    { 
    // echo child 
    } 
} 
+0

当然,你可以,但正如我在我的问题中提到的那样,这样做会随着表的增长而导致无法接受的性能问题。 –

2

根据传统的方法,我认为从SQL开始,连接表(即使在这种情况下左表和右表也是相同的),可能是一个很好的起点。

这主要是因为使用RDBMS时,您必须始终处理表格结构,并以保证数据一致性的方式连接表。

所以,开始的东西,如:

SELECT 
     a.id parent_id, a.firstname parent_name, a.lastname parent_lastname, 
     b.id child_id, b.firstname child_firstname, b.lastname child_lastname 
FROM 
     People a LEFT OUTER JOIN People b ON a.id = b.parent 
WHERE 
     a.parent = 0; 

其次,你应该更喜欢使用“fetch_all”战略(与mysqli PHP扩展,例如,但它可与PDO也),这将给你只需一次操作即可将整个结果集提取到一个二维关联数组中。

此时你可以选择你的路径。

All-PHP:您可以使用PHP遍历数组,并直接构建演示文稿标记以显示按需组织的数据,echo将html字符串指向浏览器。

AJAX:if - 例如 - 你的PHP脚本已经被AJAX调用了,你也可以走查询结果数组,但是这次解释它构建了一个JSON结构,你可以响应这个调用,这样的:

{ 
    "1": { 
     "id": 1, 
     "firstname": "James", 
     "lastname": "Donovan", 
     "children": { 
      "6": { 
       "id": 6, 
       "firstname": "Nikolai", 
       "lastname": "Donovan" 
      } 
     } 
    }, 
    "2": { 
     "id": 2, 
     "firstname": "Jeffrey", 
     "lastname": "Williams", 
     "children": { 
      "4": { 
       "id": 4, 
       "firstname": "Carol", 
       "lastname": "Williams" 
      }, 
      "5": { 
       "id": 5, 
       "firstname": "Sarah", 
       "lastname": "Williams" 
      } 
     } 
    }, 
    "3": { 
     "id": 3, 
     "firstname": "Emmit", 
     "lastname": "Herring", 
     "children": { } 
    } 
} 

这样的表示将进行数据交换更好,因为你的客户端JavaScript可以无缝地识别它,并走到它来填充一个预先存在的空表骨架。当然,你可以直接将PHP的结果数组转换为json_encode()结果数组,而不是将其重构为其他类似的东西,但是你会发现自己的东西比你已经拥有的稳定的记录集类似的数组表示方式要差得多。

最后,all-mysql解决方案是准备一个存储过程,有目的地构造你正在寻找的数据结构,例如,每个家庭1行,父母全名作为第一列,子女全名作为后续列(如果没有子女,如Emmit Herring,则为空栏)。

您可以再次使用PHP对结果集进行“fetch_all”,然后遍历数组,然后完成。所以如果性能是一个问题,最后一种方法应该保证你获得最好的结果,即使必须说服务器在计算负载和内存占用方面支付了价格,如果你打算处理大量的数据。