如何解决在MySQL中处理嵌套集?
| 我决定遵循http://www.artfulsoftware.com/mysqlbook/sampler/mysqled1ch20.html 所以现在我在寻找有关代码的帮助。 我正在使用他们的数据进行测试, 因此,我将树想象成这样: array(\'value\' => \'Richard Shakespeare\',array(\'value\' => \'Henry\',array(\'value\' => \'Joan\'),array(\'value\' => \'Margaret\'),array(\'value\' => \'William\',array(\'value\' => \'Susana\',array(\'value\' => \'Elizabeth Hall\',array(\'value\' => \'John Bernard\'))),array(\'value\' => \'Hamnet\'),array(\'value\' => \'Judith\',array(\'value\' => \'Shakespeare Quiney\'),array(\'value\' => \'Richard Quiney\'),array(\'value\' => \'Thomas Quiney\'))),array(\'value\' => \'Gilbert\'),array(\'value\' => \'Joan\',array(\'value\' => \'William Hart\'),array(\'value\' => \'Mary Hart\'),array(\'value\' => \'Thomas Hart\'),array(\'value\' => \'Micheal Hart\')),array(\'value\' => \'Anne\'),array(\'value\' => \'Richard\'),array(\'value\' => \'Edmond\')),array(\'value\' => \'John\'));
因此,如果我们要将其插入数据库中,则最终需要
Array
(
[0] => Array
(
[value] => Richard Shakespeare
[left] => 1
[right] => 46
)
[1] => Array
(
[value] => Henry
[left] => 2
[right] => 43
)
[2] => Array
(
[value] => Joan
[left] => 3
[right] => 4
)
[3] => Array
(
[value] => Margaret
[left] => 5
[right] => 6
)
[4] => Array
(
[value] => William
[left] => 7
[right] => 24
)
[5] => Array
(
[value] => Susana
[left] => 8
[right] => 13
)
[6] => Array
(
[value] => Elizabeth Hall
[left] => 9
[right] => 12
)
[7] => Array
(
[value] => John Bernard
[left] => 10
[right] => 11
)
[8] => Array
(
[value] => Hamnet
[left] => 14
[right] => 15
)
[9] => Array
(
[value] => Judith
[left] => 16
[right] => 23
)
[10] => Array
(
[value] => Shakespeare Quiney
[left] => 17
[right] => 18
)
[11] => Array
(
[value] => Richard Quiney
[left] => 19
[right] => 20
)
[12] => Array
(
[value] => Thomas Quiney
[left] => 21
[right] => 22
)
[13] => Array
(
[value] => Gilbert
[left] => 25
[right] => 26
)
[14] => Array
(
[value] => Joan
[left] => 27
[right] => 36
)
[15] => Array
(
[value] => William Hart
[left] => 28
[right] => 29
)
[16] => Array
(
[value] => Mary Hart
[left] => 30
[right] => 31
)
[17] => Array
(
[value] => Thomas Hart
[left] => 32
[right] => 33
)
[18] => Array
(
[value] => Micheal Hart
[left] => 34
[right] => 35
)
[19] => Array
(
[value] => Anne
[left] => 37
[right] => 38
)
[20] => Array
(
[value] => Richard
[left] => 39
[right] => 40
)
[21] => Array
(
[value] => Edmond
[left] => 41
[right] => 42
)
[22] => Array
(
[value] => John
[left] => 44
[right] => 45
)
)
因此,这个问题浮现在脑海,如何最好地做到这一点?
我的解决方案是:
$container = array();
function children($item){
$children = 0;
foreach($item as $node)
if(is_array($node))
$children += children($node)+1;
return $children;
}
function calculate($item,&$container,$data = array(0,0)){
//althought this one is actually of no use,it could be useful as it contains a count
$data[0]++; //$left
$right = ($data[0]+(children($item)*2))+1;
//store the values in the passed container
$container[] = array(
\'value\' => $item[\'value\'],\'left\' => $data[0],\'right\' => $right,);
//continue looping
$level = $data[1]++;
foreach($item as &$node)
if(is_array($node))
$data = calculate($node,$container,$data);
$data[1] = $level;
$data[0]++;
return $data;
}
calculate($tree,$container);
我不知道它的效率如何。
但是现在进入查询。
要选择节点的所有后代,我们可以使用
SELECT child.value AS \'Descendants of William\',COUNT(*) AS `Level`
FROM tester AS parent
JOIN tester AS child ON child.`left` BETWEEN parent.`left` AND parent.`right`
WHERE parent.`left` > 7 AND parent.`right` < 24
GROUP BY child.value ORDER BY `level`;
要选择节点的所有后代,可以使用特定深度
请注意,我们选择威廉的后代至2的深度
威廉姆斯左:7,威廉姆斯右:24,级别:2
SELECT child.value AS \'Descendants of William\',COUNT(*) AS `Level`
FROM tester AS parent
JOIN tester AS child ON child.`left` BETWEEN parent.`left` AND parent.`right`
WHERE parent.`left` > 7 AND parent.`right` < 24
GROUP BY child.value HAVING `level` <= 2 ORDER BY `level`;
因此,这很容易。
但是现在我想知道几件事,
请注意,在实际数据库以及左/右中,所有行均具有唯一的ID,以及包含其邀请者ID的\“ parent \”列;如果未邀请,则为null
假设我想在Judith
的孩子中插入David
,我该怎么做?
假设我想获得7英镑的父母和8英镑的父母父母,我该怎么做?
假设我要从ѭ10删除William Hart
怎么办?
解决方法
要更新/删除,您将需要增加/减少分支所有元素的 child.right_id的节点,如果您只希望直接祖先从以前的集合中选择一个具有最高left_id的节点。
要删除节点,请将其删除,然后降低所有大于已删除元素的右侧ID的所有左侧/右侧ID的两倍。 if(leftId> Deleted.leftId)leftId- = 2与rightId相同
插入节点为其留出一些空间,向所有节点添加+2,其中leftId> parent.rightId然后parent.rightId + = 2,然后插入leftId = parent.rightId-2和rightId = parent.rightId-1的节点
, 如果对每个关系使用DFS,然后再使用函数calculate()(如果需要更详细的信息),则可以轻松解决所有问题。
left
/right
值。
您可以在此处找到查询示例。
我不知道它的效率如何。
嵌套集对更新/插入/删除中的大树非常缓慢地起作用。而且选择速度非常快。
因此,仅将此模型与静态数据一起使用,该静态数据通常在大多数情况下都不会更改,并且该树不会包含数千个节点(或者任何更新将需要几分钟的时间才能完成)。物化路径的运行速度更快。
,
要获得节点的父节点,您需要具有left_id 版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。