5

我想选择一个根项目,它的孩子尽可能地表现出色。我更喜欢使用嵌套集模型,但这次表结构遵循邻接模型更多关于嵌套集和邻接模型

我有一个dependencies-table,还有一个items-table

依赖表

dependency_id | item_id | child_id 
            1 |       1 |        4
            2 |       2 |        5
            3 |       4 |        7
            4 |       7 |        3
            5 |       9 |        3
            6 |       1 |        2

项目表

item_id | name   | info
      1 | Item A | 1st Item
      2 | Item D | 2nd Item
      3 | Item C | 3rd Item
      4 | Item D | 4th Item
      5 | Item E | 5th Item
      6 | Item F | 6th Item

SQL,先试试

# selecting children (non-recursive)
# result: 4, 2
SELECT 
   child_id AS id 
  FROM `dependencies_table`
 WHERE item_id = 1

我需要这个 SELECT 递归。

期望的输出

# children of item #1
dependency_id | item_id | child_id
            1 |       1 |        4 // 1st level
            6 |       1 |        2 // 1st level
            2 |       2 |        5 // 2nd level, 1->2->5

这种情况应该很常见,但我想知道我现在找不到最佳实践。请注意:它是 MySQL,所以我无法使用 CTE

你将如何解决这个问题?提前致谢!

编辑:我发现了一个有趣的线程,但我的问题还没有解决。所以,请不要关闭这个问题。

编辑 2:这是一个有趣的 PHP 解决方案,但不幸的是不是我真正想要的。

4

2 回答 2

2

作为一个 NoSQL 人,我不得不说这就是图表的用途。但是是的,我明白了..使用 SQL 是有原因的,但是这个特定的例子并不是这些数据库的用途,特别是当你可以有 n 级孩子时,mysql 的执行速度会非常慢,实际上有一个查询为此,即使是 n 级,但那是一些疯狂的狗屎。(如果我没记错的话,大约是 42 个内部连接)

所以是的,你想获取表格并在 php 中做孩子们的事情。

这是获取整个依赖关系表后如何在 php 中获取结果的方法,

$dep = array();
$dep[] = array('item_id' =>'1', 'child_id' =>'4');
$dep[] = array('item_id' =>'2', 'child_id' =>'5');
$dep[] = array('item_id' =>'4', 'child_id' =>'7');
$dep[] = array('item_id' =>'7', 'child_id' =>'3');
$dep[] = array('item_id' =>'9', 'child_id' =>'3');
$dep[] = array('item_id' =>'1', 'child_id' =>'2');

function getchilds($dependencies, $id) {

    $ref = array();
    foreach($dependencies as $dep){
        $item_id = $dep['item_id'];
        $child = $dep['child_id'];
        if(!is_array($ref[$item_id])) $ref[$item_id] = array('id' => $item_id);
        if(!is_array($ref[$child])) $ref[$child] = array('id' => $child);
        $ref[$item_id]['children'][] = &$ref[$child];
    }
    return $ref[$id];
}

getchilds($dep,1);

这使用 References 只浏览每个项目一次,我无法想象任何性能更高的东西,它适用于无限数量的级别。实际上,我敢打赌,这比固定级别数量的任何 SQL 查询都要快。

对于第一项,这基本上会给你

1 - 2 - 5
 \ 
  4 - 7 - 3
于 2013-09-21T20:16:24.983 回答
1

Oracle 允许使用 分层查询CONNECT BY PRIOR,但 MySQL 不支持。因此,这最好在编程语言中完成

也就是说,如果您必须在 SQL 中执行此操作并接受固定的递归深度,则可以使用一组凌乱的自连接与UNION. 例如,这递归三个级别:

SELECT a.child_id
  FROM dependencies_table a
  WHERE a.item_id = '1'
UNION
SELECT b.child_id
  FROM dependencies_table a
  JOIN dependencies_table b ON (a.child_id = b.item_id)
  WHERE a.item_id = '1'
UNION
SELECT c.child_id
  FROM dependencies_table a
  JOIN dependencies_table b ON (a.child_id = b.item_id)
  JOIN dependencies_table c ON (b.child_id = c.item_id)
  WHERE a.item_id = '1'

产生以下结果作为在某种程度上依赖于项目 1 的项目:

4
2
5
7
3

SQL小提琴

于 2013-09-21T20:04:11.037 回答