【问题标题】:One to many relationship in MySQL, Selecting "child" table informationMySQL中的一对多关系,选择“子”表信息
【发布时间】:2011-10-17 21:17:50
【问题描述】:

我编写了一些 PHP 脚本,以便更轻松地从一系列 MySQL 表中提取信息,但是存在严重的性能问题。因此,我试图减少查询的数量。

这些表具有一对多的关系: 父表(parent_id、first、last、phone) 子表(child_id、parent_id、日期、请求、详细信息)

因此,对于父表中的任何条目,子表中可能有多个关联的行。如何在父表中选择一行并使用 parent_id(主键)从子表中提取所有关联行?

SELECT * FROM `Parent Table` WHERE `parent_id` = 5 

...然后...

SELECT * FROM `Child Table` WHERE `parent_id` = '5'

然后我想将结果放入关联数组中,然后将 json_encode 作为 JSON 返回。

为了澄清,我已经有了这个工作,但它对选择的每一行执行额外的查询,所以它不是一个查询,而是对 100 行执行 101。

任何帮助将不胜感激,在此先感谢。

更新:有人建议使用Join,但是出现了一个新问题

样本数据: 父表 (1, 'albert', 'smith', '12345') 子表 (1, 1, 2010-10-5, 'test', 'etc etc'), (2, 1, 2010-10-6, 'again', 'eg eg')

进行连接会产生两行

1, albert, smith, 12345, 1, 1, 2010-10-5, test 等

1, albert, smith, 12345, 2, 1, 2010-10-6, 再次,例如,例如

所以,我有两行父表信息重复。要使用连接,我需要某种方式来清理它,并将其放入分层表单中。

结果应该是 {parent_id:1, first:albert, last:smith, phone:12345, child_table:[{child_id:1, date:2010-10-5, request:test, details:'etc etc'},{child_id:2, date:2010-10-6, request:again, details:'eg eg'}]}

解决方案:所以,我的答案是使用连接,并编写一个函数将返回的行转换为关联数组

mysqlResult 是来自 mysql_query 调用的关联数组, parent_key 是父表的主键名, child_key 是子表的主键名, child_table 是子表的名称, child_fields 是子表中所有字段名称的关联数组

   function cleanJoin($mysqlResult, $parent_key, $child_key, $child_table, $child_fields)
    {
    $last_parent = 0;
    $last_child = 0;
    $ch_ctr = 0;

    for ($i = 0; $i < count($mysqlResult); $i++)
    {
        if ($mysqlResult[$i][$child_key] != $last_child)
        {
            echo "new child!";
            $pr_ctr = count($answer[$i]);
            foreach ($child_fields as $field => $type)
            {
               $answer[$pr_ctr][$child_table][$ch_ctr][$field] = $mysqlResult[$i][$field];
               unset($mysqlResult[$field]);
            }
            $ch_ctr++;
        }
        if ($mysqlResult[$i][$parent_key] != $last_parent)
        {
            foreach($mysqlResult[$i] as $field => $value)
            {
                $answer[$i][$field] = $value;
            }
        }
        $last_parent = $mysqlResult[$i][$parent_key];
        $last_child = $mysqlResult[$i][$child_key];
    }

    return $answer;
}

【问题讨论】:

  • 如果你不能切换到嵌套集合模型,你或多或少是不走运的,因为 MySQL 缺乏对递归查询的支持。
  • 我只是不确定如何过渡。也许一个更好的例子是有一个帖子,然后是该帖子的一系列 cmets。 cmets 存储在一个单独的表中,但有 post_id 链接到它。然后我怎么能拉出柱子和所有的cmets?或者,我怎么能在嵌套集合模型中使用它?
  • 您的表格没有显示层次结构,只是帖子和评论之间的一对多关系。您真的需要 cmets 上的 cmets 吗?和 cmets 上的 cmets 到 cmets?
  • 这只是一个例子,帖子的cmets仍然是一个层次结构。即使那样,听起来也没有办法做到这一点?
  • 是的,但是当您需要许多(或无限)级别时,您应该使用分层结构。

标签: php mysql json hierarchical-data


【解决方案1】:

也许我读错了问题,但你看过联接吗?

SELECT * FROM `Parent Table` 
join `Child Table` ON `Child Table`.`Parent ID`=`Parent Table`.`ID`
WHERE `parent_id` = 5 

整合数据的关联数组示例

 $res = mysql_query($sql);

 $output = array();

 while ($row = mysql_fetch_assoc($res)) {

    $parent_name = $row['parent_name'];  
    $child_name = $row['child_name'];

    $output[$parent_name][] = $child_name; 
}

var_dump($output);

【讨论】:

  • 这是一个很好的解决方案,我遇到的问题是每个子行都返回一行。所以,当我真的想要一行时,你最终会说 5 行,其中嵌套了 5 个子行(所以我可以返回 JSON)。我想我将不得不找到一种方法来获取许多行并将其合并到 PHP 中的关联数组中
  • 修改了答案以显示如何从查询中构建 assoc 数组结构
  • 连接的问题在于它只是将所有变量混合在一起,并添加与子表中一样多的行,并带有来自父表的重复信息。我编辑了原始帖子以解释连接问题,以及为什么我仍然需要清理数据
【解决方案2】:

我建议将您的 JSON 缓存在 PHP 文件中,并仅在发生更改时更新它

不幸的是,这种情况对数据库来说很沉重,我个人不知道有什么办法……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-01
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    相关资源
    最近更新 更多