Как использовать функцию SQL sum для сложения значений в разных таблицах MySQL с соответствующим первичным ключом? - PullRequest
0 голосов
/ 05 августа 2020

У меня было пять разных таблиц, созданных в MySQL, содержащих записи студентов. Каждая таблица в основном имеет одинаковые имена столбцов. A StudentID , Subject1_Score , Subject2_Score , Subject3_Score , Total_Score . Пять таблиц: Term1 , Term2 , Term3 , Term4 и в целом .

Что я хочу сделать, так это вставить значения в Term1 , Term2 , Term3 и Term4 , сумму баллов в каждом столбец, Subject1_Score , Subject2_Score , Subject3_Score , Total_Score должны быть автоматически рассчитаны и помещены в соответствующие столбцы в total стол. Ниже приведен код, который у меня есть. Я пытаюсь обновить таблицу total , когда вставляю оценки в таблицу Term1 . В настоящий момент он получает общую сумму столбца Total_Score . Я хочу, чтобы он взял значение Total_Score в Term1 и добавил его к значению Total_Score в total , а затем поместил его внутрь общее как обновленное текущее значение. Ниже мой код. Пожалуйста, помогите мне достичь того, что я хочу делать.

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;

1 Ответ

0 голосов
/ 05 августа 2020

Ваш текущий дизайн не нормализован и означает, что для достижения того, что вы хотите, требуется много усилий.

Для КАЖДОЙ таблицы терминов создайте до и после триггера вставки, до и после триггеров обновления и триггера после удаления при этом вы анализируете все таблицы, чтобы вычислить total.total. Что-то вроде этого (я создал только триггеры вставки и обновления для 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 является первичным ключом для всех таблиц

Вы можете обойтись без триггеров before, если ваша версия mysql поддерживает сгенерированные столбцы, НО вам действительно не следует хранить данные, которые можно легко вычислить.

ЕСЛИ ваш db был нормализован, тогда весь этот код исчезает. Рассмотрим таблицу studentid, term, subject, subject_score

...