在 WHERE 子句中使用聚合函数来更新表
Posted
技术标签:
【中文标题】在 WHERE 子句中使用聚合函数来更新表【英文标题】:Using aggregate function in WHERE clause to UPDATE a table 【发布时间】:2017-05-11 13:32:20 【问题描述】:我有两个表 employee 和 department。它们与 dep_id 列相关联,该列是 departments 中的主键和 employee 中的外键。
我的目标是:
更新所有工资高于其部门平均工资的员工的工资。 现在我有 2 个查询可以做到这一点:
UPDATE employee E
SET E.payroll = E.payroll + 1000
WHERE E.payroll > (SELECT AVG(E2.payroll) FROM employee E2 WHERE E.dep_id = E2.dep_id)
我收到一个错误:#1093 - 表“E”被指定了两次,既作为“更新”的目标,又作为数据的单独源
2) 在 department 表中,我存储每个部门的员工数量和每个部门的总工资
UPDATE employee E
SET E.payroll = E.payroll + 1000
WHERE E.payroll > (SELECT department.dep_payroll / department.dep_amount FROM department WHERE department.dep_id = E.dep_id)
这个工作正常,但是因为我有一个触发器,它在更新 employee 表和更新 dep_payroll 之后触发(我检查了两种方式)它阻止我执行第二个查询,给出这个错误 #1442 - 无法更新存储函数/触发器中的表“部门”,因为它已被调用此存储函数/触发器的语句使用。 在这里
CREATE TRIGGER `t3` BEFORE UPDATE ON `employee`
FOR EACH ROW UPDATE department
SET dep_payroll = dep_payroll - OLD.payroll + NEW.payroll
WHERE dep_id = NEW.dep_id
如何执行更新查询?
【问题讨论】:
How to UPDATE from a SELECT in SQL Server? 的可能重复 用于更新 mysql 数据库的规则是相同的,因为它是标准的 T-SQL 语言。 @MaciejLos,我没看到那个。但是第二个查询呢? IIRC 这是 MySQL 的一个缺陷。您不能使用在 where 子句中更新的同一个表。但是,当您更深一层时,它通常会起作用。类似于WHERE E.payroll > (SELECT * FROM (SELECT AVG(E2.payroll) FROM employee E2 WHERE E.dep_id = E2.dep_id) x)
。
@ThorstenKettner,太神奇了,谢谢!我会在答案中发布
【参考方案1】:
考虑一个临时表来存储要更新的员工列表。然后在单独的查询中运行更新本身:
create temporary table list (emp_id int)
;
insert list
select emp_id
from YourTable emp
join (
select dep_id
, avg(payroll) as avg_pay
from YourTable
group by
dep_id
) dep
on emp.dep_id = dep.dep_id
where payroll > avg_pay
;
update YourTable
set payroll = payroll + 1000
where emp_id in (select emp_id from list)
;
Example at regtester.
【讨论】:
【参考方案2】:我不知道这是否是编写此类查询的最有效方法,感谢@ThorstenKettner 我已经设法找到答案了
UPDATE employee E
SET E.payroll = E.payroll + 1000
WHERE E.payroll >
(SELECT * FROM
(SELECT AVG(E2.payroll) FROM employee E2 INNER JOIN employee E ON E.dep_id = E2.dep_id)
X)
但是,我的问题的第二部分仍然没有得到解答。它是 MySQL 中的缺陷还是触发器编写错误?
【讨论】:
不知道为什么你在子查询中有一个inner join
,这会多次计算很多员工。您也没有查看员工所在部门的平均工资:子查询与您正在更新的行之间没有链接。
@Andomar,好吧,我在我的示例数据库上对其进行了测试,它可以工作以上是关于在 WHERE 子句中使用聚合函数来更新表的主要内容,如果未能解决你的问题,请参考以下文章