如何使用 SQL sum 函数在不同的 MySQL 表中添加具有相应主键的值?

Posted

技术标签:

【中文标题】如何使用 SQL sum 函数在不同的 MySQL 表中添加具有相应主键的值?【英文标题】:How do I use the SQL sum function to add values in different MySQL tables with the corresponding Primary Key? 【发布时间】:2020-08-05 06:33:12 【问题描述】:

我在 mysql 中创建了五个不同的表,其中包含学生记录。每个表基本上都有统一的列名。 StudentIDSubject1_ScoreSubject2_ScoreSubject3_ScoreTotal_Score。这五个表是Term1Term2Term3Term4overall

我想要做的是当我将值插入 Term1Term2Term3Term4 时,每列分数的总和,Subject1_ScoreSubject2_ScoreSubject3_ScoreTotal_Score必须自动计算并放置在 overall 表的相应列中。下面是我的代码。当我将分数插入 Term1 表时,我正在尝试更新 overall 表。它目前正在做的是获取 Total_Score 列的总和。我希望它获取 Term1Total_Score 的值,并将其添加到 overallTotal_Score 的值中,然后然后将其放入 overall 作为更新后的当前值。下面是我的代码。请帮助我实现我想做的事情。

SELECT SUM( Total_Score ) 
FROM (


SELECT SUM( Total_Score ) AS Total_Score
FROM Term1
UNION ALL 
SELECT SUM( Total_Score ) AS Total_Score
FROM overall
) AS ALIAS;

【问题讨论】:

这个问题让我很困惑:( 对不起。我将再次简化我的问题。 您是否能够以更规范的方式重新设计您的数据库? 为什么你有5个相同的表?并查看meta.***.com/questions/333952/… 修复你的数据模型!不要试图让损坏的数据模型工作。您不应将一个实体分布在五个表中。 【参考方案1】:

您当前的设计尚未标准化,这意味着您需要付出很多努力才能实现您想要的。

对于每个术语表,在插入触发器之前和之后创建、更新触发器之前和之后以及删除触发器之后,您可以在其中解析所有表以计算总体总数。像这样的东西(我只为 term1 创建了插入和更新触发器以减少答案大小)

drop trigger if exists trigger_after_term1_insert;
drop trigger if exists trigger_before_term1_insert;
drop trigger if exists trigger_after_term1_update;
drop trigger if exists trigger_before_term1_update;

delimiter $$
create trigger trigger_term1_before_insert before insert on term1
for each row
begin
  insert into debug_table(msg) values (concat('before insert:',new.subject1_score + new.subject2_score + new.subject3_score));
  set new.total = new.subject1_score + new.subject2_score + new.subject3_score; #you may need coalesce here
end $$

delimiter $$
create trigger trigger_term1_before_update before update on term1
for each row
begin
  insert into debug_table(msg) values (concat('before update:',new.subject1_score + new.subject2_score + new.subject3_score));
  set new.total = new.subject1_score + new.subject2_score + new.subject3_score; #you may need coalesce here
end $$

delimiter $$
create trigger trigger_term1_after_insert after insert on term1
for each row
begin
 insert into debug_table(msg) values ('after insert');
 if not exists (select 1 from overall o where o.studentid = new.studentid) then
         insert into debug_table(msg) values ('after insert Not exists');
        insert into overall(studentid,total)
                select studentid,sum(tot) 
                 from
                 (
                 select new.studentid,new.subject1_score + new.subject2_score + new.subject3_score tot
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term2 #amend as required
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term3 #amend as required
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term4 #amend as required
                 ) b
                 group by studentid;
       end if;
end $$

delimiter $$
create trigger trigger_term1_after_update after update on term1
for each row
begin
 insert into debug_table(msg) values ('after update');
 if exists (select 1 from overall o where o.studentid = new.studentid) then
    insert into debug_table(msg) values ('after update exists');
    update overall 
           join (select studentid,sum(tot) tot
                 from
                 (
                 select new.studentid,new.subject1_score + new.subject2_score + new.subject3_score tot
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term2 #amend as required
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term3 #amend as required
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term4 #amend as required
                 ) a
                 group by studentid
                 ) s
                 on s.studentid = overall.studentid
         set overall.total = s.tot;
      else
         insert into debug_table(msg) values ('after update Not exists');
        insert into overall(studentid,total)
                select studentid,sum(tot) 
                 from
                 (
                 select new.studentid,new.subject1_score + new.subject2_score + new.subject3_score tot
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term2 #amend as required
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term3 #amend as required
                 union all
                 select studentid,subject1_score + subject2_score + subject3_score from term4 #amend as required
                 ) b
                 group by studentid;
       end if;
        
 
end $$
delimiter ;

注意 1) debug_table 可以帮助调试 2) studentid 是所有表的主键

如果你的 mysql 版本支持生成的列,你可以省略之前的触发器,但你真的不应该存储可以轻松计算的数据。

如果您的数据库被规范化,那么所有这些代码都会消失。 考虑一张桌子 studentid,term,subject,subject_score

【讨论】:

以上是关于如何使用 SQL sum 函数在不同的 MySQL 表中添加具有相应主键的值?的主要内容,如果未能解决你的问题,请参考以下文章

mysql 如何让sum函数保留小数位

使用函数 SUM() 和 Group by 将 Mysql 查询转换为 SQL 查询

mysql SQL语句如何将sum()放在where后面做条件怎么写呢?

SQL SUM() 函数

MYSQL sum() 用于不同的行

mysql基础-mysql中的DQL-分组函数