表被指定两次,既作为'UPDATE'的目标,又作为mysql中数据的单独源

hri*_*shi 31 mysql

我有以下MySQL查询,我要检查,如果分支ID年度财务从类型branch_master与平等的分支ID一年经理然后更新状态经理对表分行ID经理

UPDATE manager as m1 
  SET m1.status = 'Y'
  WHERE m1.branch_id IN (
    SELECT m2.branch_id FROM manager as m2 
     WHERE (m2.branch_id,m2.year) IN (
        (
          SELECT DISTINCT branch_id,year 
            FROM `branch_master` 
           WHERE type = 'finance'
        )
     )
  )
Run Code Online (Sandbox Code Playgroud)

但得到错误

表'm1'被指定两次,既作为'UPDATE'的目标,又作为单独的数据源

Tho*_*ner 69

这是一个典型的MySQL事物,通常可以通过从派生表中选择来避免,即代替

FROM manager AS m2
Run Code Online (Sandbox Code Playgroud)

使用

FROM (select * from manager) AS m2
Run Code Online (Sandbox Code Playgroud)

完整的声明:

UPDATE manager
SET status = 'Y'
WHERE branch_id IN
(
  select branch_id
  FROM (select * from manager) AS m2
  WHERE (branch_id, year) IN
  (
    SELECT branch_id, year
    FROM branch_master
    WHERE type = 'finance'
  )
);
Run Code Online (Sandbox Code Playgroud)

  • 这真是难过;这真是伤心.它表明MySQL的优化器在这里做得不好. (3认同)

sha*_*yyx 6

正确的答案在这篇 SO 帖子中。

这里接受的答案的问题是 - 正如已经多次提到的 - 创建整个表的完整副本。这远非最佳且空间最复杂的一种。这个想法是具体化仅用于更新的数据子集,所以在您的情况下它会是这样的:

UPDATE manager as m1
SET m1.status = 'Y'
WHERE m1.branch_id IN (
    SELECT * FROM(
        SELECT m2.branch_id FROM manager as m2 
        WHERE (m2.branch_id,m2.year) IN (
            SELECT DISTINCT branch_id,year 
            FROM `branch_master` 
            WHERE type = 'finance')
    ) t
)
Run Code Online (Sandbox Code Playgroud)

基本上,您只需将之前的数据查询源封装在

SELECT * FROM (...) t
Run Code Online (Sandbox Code Playgroud)