更新MySQL表中的已连接组件

时间:2014-07-09 20:44:11

标签: mysql sql sql-update graph-theory

假设我有一个MySQL表,它定义了一组东西,每个东西都与1或2个所有者相关联。例如:

CREATE TABLE thing (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT
    , name CHAR(10)
    , first_owner INT UNSIGNED NOT NULL
    , second_owner INT UNSIGNED DEFAULT NULL
    );

+----+------------+-------------+--------------+
| id | name       | first_owner | second_owner |
+----+------------+-------------+--------------+
| 1  | skateboard | Joe         | NULL         |
| 2  | flashlight | Joe         | NULL         |
| 3  | drill      | Joe         | Erica        |
| 4  | computer   | Erica       | NULL         |
| 5  | textbook   | Diane       | NULL         |
| 6  | cell phone | Amy         | Diane        |
| 7  | piano      | Paul        | Amy          |
+----+------------+-------------+--------------+

每个不同的所有者是图的节点,同一行中的两个所有者构成其节点之间的边。从上面的示例行中绘制的图形如下所示:

在这个例子中,有两个组成部分:Joe和Erica是一个组件;黛安,保罗和艾米是另一个。

我想在表格中识别这些组件,因此我添加了另一列:

ALTER TABLE thing ADD COLUMN `group` INT UNSIGNED;

如何编写UPDATE语句,通过唯一标识该行所属的连接组件来填充此新列?以下是上述示例行的可接受结果的示例:

+----+------------+-------------+--------------+-------+
| id | name       | first_owner | second_owner | group |
+----+------------+-------------+--------------+-------+
| 1  | skateboard | Joe         | NULL         | 1     |
| 2  | flashlight | Joe         | NULL         | 1     |
| 3  | drill      | Joe         | Erica        | 1     |
| 4  | computer   | Erica       | NULL         | 1     |
| 5  | textbook   | Diane       | NULL         | 2     |
| 6  | cell phone | Amy         | Diane        | 2     |
| 7  | piano      | Paul        | Amy          | 2     |
+----+------------+-------------+--------------+-------+

我可以使用存储过程执行此操作,但是我的实际场景涉及更多表和数百万行,所以我希望有一种聪明的方法来执行此操作而不用循环游标一周。

这是用于说明问题的简化示例。每个组件应该代表一个“家庭”,大多数只有1或2个节点,但那些节点更多的节点尤为重要。家庭的规模没有一定的严格上限。

2 个答案:

答案 0 :(得分:-1)

您可以考虑这种创建hierarchical queries in mysql

的方法
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
        DECLARE _id INT;
        DECLARE _parent INT;
        DECLARE _next INT;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

        SET _parent = @id;
        SET _id = -1;

        IF @id IS NULL THEN
                RETURN NULL;
        END IF;

        LOOP
                SELECT  MIN(id)
                INTO    @id
                FROM    t_hierarchy
                WHERE   parent = _parent
                        AND id > _id;
                IF @id IS NOT NULL OR _parent = @start_with THEN
                        SET @level = @level + 1;
                        RETURN @id;
                END IF;
                SET @level := @level - 1;
                SELECT  id, parent
                INTO    _id, _parent
                FROM    t_hierarchy
                WHERE   id = _parent;
        END LOOP;       
END

另外,关于这个主题的一篇非常好的文章Adjacency list vs. nested sets: MySQL

答案 1 :(得分:-1)

对相关问题非常好answer

  

" 将平面表解析为一个最有效/优雅的方法是什么?   ?树"

     

有几种方法可以在关系中存储树形结构数据   数据库。您在示例中显示的内容使用两种方法:

     
      
  • 邻接列表("父"列)和
  •   
  • 路径枚举(名称列中的虚线数字)。
  •   
     

另一种解决方案叫做嵌套集,它可以存储在   同样的表。阅读" Trees and Hierarchies in SQL for Smarties"通过   Joe Celko提供了有关这些设计的更多信息。

     

我通常更喜欢名为关闭表的设计(又名"邻接   Relation")用于存储树形结构数据。它需要另一个   表,但是查询树很容易。

请查看原始问题以供参考。