Postgresql

PostgreSQL:避免多次對相同的值求和

  • June 24, 2015

我有一張學生表和一張不同科目的分數表。我想對所有科目的每個學生的 score1 和 score2 求和,然後為每個學生添加獎金。

CREATE TABLE student (
  id serial PRIMARY KEY,
  name text NOT NULL,
  bonus integer NOT NULL,
);

CREATE TABLE score (
 id serial PRIMARY KEY,
 subject text NOT NULL,
 score1 integer NOT NULL,
 score2 integer NOT NULL,
 student_id integer NOT NULL,
 CONSTRAINT s_id FOREIGN KEY (student_id) REFERENCES student (id),
);

加入 score1 & score2 的查詢如下所示:

SELECT st.name, sum(sc.score1 + sc.score2) as total
FROM student st
LEFT JOIN score sc ON sc.student_id = st.id
group by st.name

如果我添加bonus到這個查詢 ie sum(sc.score1 + sc.score2 + st.bonus),它會為每個學生重複多次(取決於 student_id 在分數表中出現的次數)。

我是否必須使用子查詢,即先計算 score1 和 score2 的總和,然後將其添加到獎金中(見下文),還是有更好的方法?

SELECT sq.name, sum(sq.bonus+sq.total) FROM
( SELECT st.bonus, st.name, sum(sc.score1 + sc.score2) as total
 FROM student st
 LEFT JOIN score sc ON sc.student_id = st.id
 group by st.name
) AS sq

您可以使用子查詢,但您不需要。只是不要總結bonus並將其添加到GROUP BY列表中。

請注意student.id,即使在原始查詢中,您也必須添加 ,以防您有 2 個同名的學生。

您可能還需要coalesce()沒有任何分數的學生:

SELECT st.name, 
      coalesce(sum(sc.score1),0) + coalesce(sum(sc.score2),0) + st.bonus AS total
FROM student st
LEFT JOIN score sc ON sc.student_id = st.id
GROUP BY st.id, st.name, st.bonus ;

student在較新版本的 Postgres 中,您可以通過以下方式僅使用組中表的主鍵:

SELECT st.name, 
      coalesce(sum(sc.score1),0) + coalesce(sum(sc.score2),0) + st.bonus AS total
FROM student st
LEFT JOIN score sc ON sc.student_id = st.id
GROUP BY st.id ;

如果你想要一個子查詢,這是一種方法:

SELECT st.name, 
      coalesce(sc.score, 0) + st.bonus AS total
FROM student st
LEFT JOIN 
   ( SELECT student_id, sum(score1) + sum(score2) AS score
     FROM score 
     GROUP BY student_id
   ) AS sc ON sc.student_id = st.id ;

引用自:https://dba.stackexchange.com/questions/105017