【问题标题】:Trying to update a table related to multiple other rows in the same table尝试更新与同一个表中的多个其他行相关的表
【发布时间】:2014-07-31 14:55:18
【问题描述】:

我有一个表,它使用具有典型左右列(trLeft 和 trRight)的嵌套集来表示一棵树。为了优化,我还在树中包含了行的级别,即它在树 ROOT 之前的父级数量。

在嵌套集中,A 行的父行是所有其他 B 行,其中 B.trLeft < A.trLeft AND B.trRight > A.trRight

因此计算这些行将返回级别,从而导致以下更新查询开始,以便更新具有正确级别的所有行:

UPDATE Groups AS g1 SET g1.trLevel = ( 
    SELECT COUNT(*) FROM Groups AS g2 WHERE g2.trLeft < g1.trLeft AND g2.trRight > g1.trRight ) ;

但这会导致错误 1093“您无法在 FROM 子句中指定目标表 'g1' 进行更新。

有没有办法解决这个问题?

【问题讨论】:

    标签: mysql sql mariadb


    【解决方案1】:

    您必须将计数嵌套在选择中。我认为这会奏效:

    EDITED: Updated query

    UPDATE Groups SET trLevel = (
        SELECT * FROM 
        (
            SELECT COUNT(*) FROM Groups g2 inner join Groups g1 on g2.unique_id = g1.unique_id WHERE g2.trLeft < g1.trLeft AND g2.trRight > g1.trRight 
        ) AS my_count
    ) ;
    

    AS my_count 很重要,因为它告诉 MySQL 从这个查询创建一个 tmp 表。然后将 my_count tmp 表用作 UPDATE 语句的源。

    【讨论】:

    • 感谢您的建议,但不起作用。原因是您使用 AS my_count 创建了一个派生表,该表无法从主查询中引用列,导致错误 1054 “Unknown column t1.trLeft in where 子句”
    • 我的错,请查看我更新的查询。本质上,我们正在连接同一张表中的两列(如您所见)。这应该起作用的原因是我们在派生表中定义了 g1 和 g2。
    • 我看不出这如何解决问题。我理解 unique_id 是行的唯一 ID,即主键。如果是这样,则连接同一行,这会导致 where 子句始终为 false,并且计数为 0。此外,由于 all 是在派生表中定义的,因此实际更新的行与派生表结果之间没有链接,即结果在范围内无效。
    【解决方案2】:

    一个愚蠢的解决方法是将派生表嵌套在子查询中,如下所示:

    UPDATE Groups AS g1 
    SET g1.trLevel = (
      SELECT COUNT(*) 
      FROM ( 
        SELECT *
        FROM Groups AS g2 
      ) AS temp
      WHERE 
        temp.trLeft < g1.trLeft 
        AND temp.trRight > g1.trRight 
    );
    

    我首先像这样构建表来测试这个:

    CREATE TABLE Groups (trLeft int, trRight int, trLevel int);
    
    INSERT INTO Groups (trLeft, trRight) VALUES (1, 4), (5, 6), (2, 3);
    

    它有效。

    【讨论】:

    • 不幸的是,与上一张海报的评论相同。 “内部”查询不是子查询,而是派生表,这也是它需要名称(AS temp)的原因。在派生表中,不能引用外部查询列。
    • 发现mySQL也在嵌套查询中定位冲突。我修改了您的查询,通过将条件移动到 WHERE 子句来避免派生表问题:UPDATE Groups AS g1 SET g1.trLevel = ( SELECT COUNT(*) FROM ( SELECT * FROM Groups AS g2 ) AS g3 WHERE g3.trLeft &lt; g1.trLeft AND g3.trRight &gt; g1.trRight ); 这导致相同的初始 1093 错误代码
    • 你说得对,我当时无法测试,但现在可以了。我编辑了我的答案。它与您的回复几乎相同,但它在我的数据库中工作。
    • 感谢您的更新。出于同样的原因,对我仍然不起作用。你不是在 mySQL 上测试,是吗?
    • 是的,我正在使用 MySQL。你不是吗?你的标签上写着 MySQL
    猜你喜欢
    • 2011-07-25
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2011-12-14
    • 2021-02-17
    相关资源
    最近更新 更多