MySQL查询从嵌套集中获取节点的完整路径

时间:2012-12-14 19:27:03

标签: mysql postgresql path sphinx nested-sets

我有嵌套的set table(MySQL),里面有大约150万条记录。 表结构是:

id | name | root_id | lft | rgt | level

我需要获取字符串,包含所有父记录的名称和记录名称,我们称之为'full_name'。 例如,它将是

"United States, California, Los Angeles"

表示“洛杉矶”记录。

我可以用以下内容查询ONE记录的所有名称:

SELECT parent.name
FROM location AS node,
     location AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND parent.root_id=node.root_id AND node.id=:id
ORDER BY parent.level

并使用implode()

构建full_name

但是此请求仅适用于一个记录,对于多个呼叫而言工作太慢。 所以现在我想将'full_name'添加到Sphinx索引(或者可能直接添加到MySQL)。

问题:

  • 是否可以构造这样的sql查询,为每条记录选择'full_name'以将其放入Sphinx索引?我认为这对于这种情况来说是理想的解决方案。

  • 我还尝试更新添加'full_name'字段的MySQL表,但我的更新请求将需要几天才能完成作业。总的来说这是个好主意吗?是否有可能使此更新足够快?

  • 我在想,也许我应该转移到PostgreSQL并使用分层请求(我对这个数据库没有经验,所以不能确定)?

谢谢

1 个答案:

答案 0 :(得分:0)

当您说您要更新表以添加full_name字段时,您是说您是单独为每条记录运行上述查询吗?

真的不应该那么慢,桌面上有适当的索引吗?

无论如何,只需运行一个实际查询即可更快地获取所有记录。这里的功能: http://www.sitepoint.com/hierarchical-data-database-2/

可以轻松修改,更新所有recrds。只是不是打印出缩进列表,循环的每次迭代都应该运行一个更新语句。除了维护$ right数组外,还需要维护一个字符串列表。添加/删除右边的位置同时添加另一个数组。

// start with an empty $right stack
$right = array();
$names = array();

// now, retrieve whole tree
$result = mysql_query('SELECT id, name, full_name, lft, rgt FROM location ORDER BY lft ASC');

// update each row
while ($row = mysql_fetch_array($result)) {
    // only check stack if there is one
    if (count($right)>0) {
        // check if we should remove a node from the stack
        while ($right[count($right)-1]<$row['rgt']) {
            array_pop($right);
            array_pop($names);
        }
    }

    // add this node to the stack
    $right[] = $row['rgt'];
    $names[] = $row['name'];

    if (empty($row['full_name'])) {
        mysql_query("UPDATE location SET full_name='".mysql_real_escape_string(implode(', ',$names))."' WHERE id=".intval($row['id']));
    }
}

如果仍然很慢,而不是更新原始表,请将full_name(以及id)插入到新表中 - 没有任何索引。更改表以在id列上添加索引,然后运行多表更新,以从temporally表更新主表。这样会更快,因为它不是零碎地更新主要索引,而是在一大批上进行。