我在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'
)
)
)
但是收到错误
表'm1'被指定两次,既作为'UPDATE'的目标又作为a 单独的数据来源
答案 0 :(得分:54)
这是一个典型的MySQL事物,通常可以通过从派生表中选择来避开,即代替
FROM manager AS m2
使用
FROM (select * from manager) AS m2
完整陈述:
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'
)
);
答案 1 :(得分:1)
尝试:::
UPDATE manager as m1
SET m1.status = 'Y'
WHERE m1.branch_id IN (
(SELECT DISTINCT branch_id
FROM branch_master
WHERE type = 'finance'))
AND m1.year IN ((SELECT DISTINCT year
FROM branch_master
WHERE type = 'finance'))
答案 2 :(得分:1)
尝试使用EXISTS
运算符:
UPDATE manager as m1
SET m1.status = 'Y'
WHERE EXISTS (SELECT 1
FROM (SELECT m2.branch_id
FROM branch_master AS bm
JOIN manager AS m2
WHERE bm.type = 'finance' AND
bm.branch_id = m2.branch_id AND
bm.year = m2.year) AS t
WHERE t.branch_id = m1.branch_id);
注意:该查询使用@Thorsten建议的其他嵌套级别,作为绕过 Table指定两次错误的方法。
答案 3 :(得分:0)
也许不是一个解决方案,但是首先考虑了为什么它不起作用:
从表中读取数据并将数据写入同一表中有些定义不明确。应该以什么顺序读取和写入数据?从同一张表读回时,应考虑新写入的数据吗? MySQL拒绝执行此命令不仅是由于局限性,还因为它不是一项定义明确的任务。
涉及SELECT ... FROM (SELECT * FROM table) AS tmp
的解决方案只是将表的全部内容转储到临时表中,然后可以将其用于任何其他外部查询中,例如更新查询。这将强制操作顺序为:首先将所有内容都选择到临时表中,然后然后使用该数据(而不是原始表中的数据)进行更新。
但是,如果所涉及的表很大,那么此临时复制将非常慢。没有索引会加速SELECT * FROM table
。
我今天可能会过得很慢...但是原始查询与此不相同,哪一个没有问题?
UPDATE manager as m1
SET m1.status = 'Y'
WHERE (m1.branch_id, m1.year) IN (
SELECT DISTINCT branch_id,year
FROM `branch_master`
WHERE type = 'finance'
)
答案 4 :(得分:0)
我接受的答案存在的问题是创建整个表的副本,但对于我来说这不是一个选择,我尝试执行该表,但几个小时后不得不取消它。
如果您有大量数据,一种非常快速的方法是创建一个临时表:
创建TMP表
创建临时表tmp_manager (branch_id bigint auto_increment主键, 年datetime null);
填充TMP表
插入tmp_manager(branch_id,年份) 选择branch_id,年份 来自经理;
使用连接进行更新
更新管理器为m,tmp_manager为tmp_m 内部JOIN管理器作为tmp_m.branch_id = man.branch_id上的人 SET状态=“ Y” 其中m.branch_id = tmp_m.branch_id和m.year = tmp_m.year且m.type ='finance';
答案 5 :(得分:0)
正确答案在this SO post中。
这里接受的答案的问题是-正如多次提到的那样-创建整个表的完整副本。这离最佳和最复杂的空间还很远。想法是实现仅用于更新的数据子集,因此在您的情况下将是这样的:
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
)
基本上,您只是将以前的数据源查询封装在
中SELECT * FROM (...) t
答案 6 :(得分:0)
这是迄今为止最快的方法:
{{1}}
请注意,如果是1:n关系,则SET命令将运行多次。在这种情况下,这没问题。但是,如果您有类似“ SET price = price + 5”的信息,则无法使用此构造。