在 WHERE 子句中使用聚合函数来更新表

Posted

技术标签:

【中文标题】在 WHERE 子句中使用聚合函数来更新表【英文标题】:Using aggregate function in WHERE clause to UPDATE a table 【发布时间】:2017-05-11 13:32:20 【问题描述】:

我有两个表 employeedepartment。它们与 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 子句中使用聚合函数来更新表的主要内容,如果未能解决你的问题,请参考以下文章

为啥聚合函数不能放在where后面?

SQL WHERE 子句中的聚合函数

如何对where子句中的数据字段和聚合函数进行算术运算?

SQLite 中 WHERE 子句中的聚合函数

为啥不能再where语句中直接使用聚合函数

(转)Where与Having的总结