0

我正在尝试运行以下查询:

update list
set li = '6'
where li = '5'
and dn in ( SELECT dn FROM list GROUP BY dn HAVING COUNT(*) < 2000 )

此查询导致上述错误:

You can't specify target table 'list' for update in FROM clause

因此,我从建议我运行以下命令的人那里得到了建议:

START TRANSACTION;
UPDATE  list a
    INNER JOIN
    (
        SELECT  dn 
        FROM    list 
        GROUP   BY dn 
        HAVING  COUNT(*) < 2000 
    ) b ON a.dn = b.dn
SET     a.li = '6'
WHERE   a.li = '5';

此代码运行 - 问题是它永远不会完成。我不确定这是声明本身的问题,还是因为它试图自己处理 400 万条记录,但我昨晚睡觉时让它继续存在,今天早上还没有完成。另外,只是事后的想法:我确实尝试将其放入事务中,以防万一事情变得糟糕,因此投入了“开始事务;” 在这开始。

我的印象是这是一个相当普遍的问题——但不幸的是,我对 SQL 的了解不足以接受别人的查询并对其进行调整以适应我自己的需求。:p

谁能指导我找到允许我更新这些记录的解决方案?非常感激。

4

3 回答 3

2

这可能有效,因此,继续我上面的评论,这是一个答案:

是的,删除 '6' 和 '5' 周围的引号,您不希望 MySQLli在每次比较时将列转换为字符串......并创建索引。

CREATE idx_dn_li ON list(dn, li);

UPDATE  list a
    INNER JOIN
    (
        SELECT  dn 
        FROM    list 
        GROUP   BY dn 
        HAVING  COUNT(*) < 2000 
    ) b ON a.dn = b.dn
SET     a.li = 6
WHERE   a.li = 5;

索引将使您GROUP BY更快,我认为在其中li放置列也可以提供帮助(如我所见,在没有记录受到影响的情况下,您的查询应该只读取索引,但不要相信我的话它 ;) )

于 2013-04-23T14:02:02.393 回答
0

当我们尝试更新表并且我们在另一个查询中也有同一个表来更新列时会生成此错误。

我们无法从您同时更新的表中进行选择。但是,我们可以进行多表更新,例如

UPDATE tbl AS a
  INNER JOIN tbl AS b ON ....
  SET a.col = b.col

或尝试您的查询的简化版本

update list l1, ( SELECT dn FROM list GROUP BY dn HAVING COUNT(*) < 2000 ) AS l2
set li = '6'
where li = '5'
and dn = l2.dn

希望对您有所帮助.. 这是您的参考... http://7php.com/mysql-update-select-statement-1093/

于 2013-04-23T12:47:07.793 回答
0

询问:

update list
set li = '6'
where li = '5'
and dn in ( SELECT a.dn 
            FROM (SELECT * FROM list) a 
            GROUP BY a.dn 
            HAVING COUNT(*) < 2000 )

此查询可能会更快:

UPDATE list t
SET t.li = '6'
WHERE t.li = '5'
AND (SELECT COUNT(*)
     FROM (SELECT * FROM tik) a 
     WHERE a.dn = t.dn) < 2000
于 2013-04-23T12:50:45.353 回答