【问题标题】:MYSQL - Get all children from the parentsMYSQL - 从父母那里获取所有孩子
【发布时间】:2018-08-14 13:23:24
【问题描述】:

我一直坚持让所有孩子的查询父 ID 大于客户 ID

表格测试

  id    name    parent
    1   test1   0
    2   test2   1
    3   test3   1
    4   test4   2
    5   test5   2
    6   test6   10
    7   test7   10
    8   test8   6
    9   test9   6
    10  test10  5
    11  test10  7

目前我正在使用这个递归查询,但它显示孩子直到 10 父级,但无法提供 6 岁和 7 岁及更多的孩子

SELECT id , parent FROM (SELECT  id , parent from (SELECT * FROM test order by
parent , id) testdata_sorted, (SELECT @pv := '1') initialisation where 
find_in_set(parent , @pv) > 0 and @pv := concat(@pv, ',', id)  ORDER BY 
parent ASC) AS tt

当前输出为 ->

id  parent
2   1
3   1
4   2
5   2
10  5
6   10
7   10

我需要这种类型的输出。我需要这方面的帮助。

id  parent
2   1
3   1
4   2
5   2
10  5
6   10
7   10
8   6
9   6
11  7

【问题讨论】:

  • 您能否提供您的架构,以便我们查看相关的各种表?
  • 如果您需要父 id 大于 id 的记录,它不应该显示 id=2 的记录,因为它的父是 1 较小。 (还有更多可以找到)
  • 您不想切换到嵌套集吗?
  • 您使用什么版本的 MySQL(或 MariaDB)?这会有所不同,因为 MySQL 8+ 和 MariaDB 10.2+ 具有递归公用表表达式。 (查找这些。)
  • @SupaMonkey 你能告诉我怎么可能吗?

标签: php mysql mysqli parent-child hierarchy


【解决方案1】:

感谢大家的回复,但从目前的情况来看,我分析由于版本问题,MY SQL 无法解决此问题,因为最终此递归查询在某些时候中断。

所以我必须使用相同的查询在 PHP 中创建一个递归函数,该查询在子 ID 大于父级的地方中断,并使用该中断 ID 一次又一次地调用相同的函数,并在同一数组中添加数据。这给出了我想要的结果。

function getallchilds($customer_parent_id){

$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$downlineChilds =array();
$breakbleIds =array();

    $getallchilds = $read->fetchAll("SELECT id , parent FROM (SELECT  id , parent from (SELECT * FROM test order by
parent , id) testdata_sorted, (SELECT @pv := '".$customer_parent_id."') initialisation where 
find_in_set(parent , @pv) > 0 and @pv := concat(@pv, ',', id)  ORDER BY 
parent ASC) AS tt");

    foreach($getallchilds as $childs) {
          $downlineChilds[] =  array($customer_parent_id => $childs['id']);
          if ($childs['parent'] > $childs['id']) {
            $breakbleIds[] =  $childs['id']; 
          }
        }

    $checkbreakIDS = count($breakbleIds);
    if($checkbreakIDS > 0 ){
        foreach($breakbleIds as $breakbleId) {
            $childrens = getallchilds($breakbleId);
            if ($childrens){
                $downlineChilds = array_merge($downlineChilds,$childrens);
            }
        }
        return $downlineChilds;
    }
    else{
        return $downlineChilds;
    }

}

【讨论】:

    【解决方案2】:

    您正在使用一种脆弱的方式来模拟递归查询。它特别要求父行必须排在子行之前

    您的基本行集正在使用order by parent, id

    id  parent
    ----------------------
    1   0
    2   1         -- fine
    3   1         -- fine 
    4   2         -- fine
    5   2         -- fine 
    10  5         -- fine 
    8   6         -- parent 6 comes later!
    9   6         -- parent 6 comes later! 
    11  7         -- parent 7 comes later!
    6   10        -- fine
    7   10        -- fine
    

    您会看到这些正是您的结果中缺少的行。

    对此没有简单的解决方法,要在运行中对行进行排序以便能够在递归查询中使用,您需要递归查询。不过,您可能能够以满足该条件的方式输入您的数据。虽然我假设您问题中父 ID 大于客户 ID 的部分 实际上不是一个条件(因为您的预期输出与此不符):如果您 这样一个限制父子关系的条件,它可以给你一个可能的顺序。

    有关建模数据或编写查询的替代方法,请参阅How to create a MySQL hierarchical recursive query。实际上,trincots answer 包含有关您的代码的顺序要求的备注。

    您最好使用支持递归 CTE 的版本,因为只要您不想更改数据模型,针对这些的每个解决方法都有一些限制(例如行顺序或最大深度)。

    附注:子查询中的 order by(特别是 testdata_sorted)可以被 MySQL 忽略,您可能需要验证它是否不会(这可能取决于版本、索引或表大小等因素) .

    【讨论】:

    • 感谢您的解决方案。因为 mysql 版本是 5.7,所以 Cte 不支持那里,这就是我坚持这个位置的原因。这样做是因为默认数据对齐良好,但一段时间后我必须根据需要更改其父母孩子的数据。我希望任何人都能找到解决方案
    • 不可能为您的数据结构编写单个(非递归)查询,我希望答案对于您的查询类型来说清楚。您可以 a)使用不同的查询类型(具有其他限制,例如最大深度)或不同的模型(例如嵌套集),请参阅链接 b)确保您的数据在更新后是正确的(例如,为移动的对象分配新的 id 和他们所有的后代);使(罕见的)更新复杂化,但简化了(频繁的)选择 c)使用多个查询(例如,插入到临时表中的存储过程或 php 中的循环)(这可以/也将用于修复 b 中的 id )
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多