为每个学生选择*最新*成绩信息

时间:2010-01-27 22:50:46

标签: sql postgresql

我有两张桌子:

STUDENT        GRADES
----------     ----------
id             id
name           person_id
address        date
city           test_name
phone          grade

每个学生将在成绩表中有多个条目。我想知道是否可以使用SQL(Postgres)选择所有学生以及他们的最新成绩信息。我基本上想要一个如下所示的结果表,其中date,test_name和grade是最新结果(按日期)。

LATEST_GRADES
----------------
id
name
address
city
phone
grade_id
date
test_name
grade

非常感谢任何帮助,谢谢。

编辑:添加解决方案查询

SELECT * FROM
  students s
  JOIN (SELECT DISTINCT ON (person_id) person_id, date, test_name, grade
      FROM grades
      ORDER BY person_id, date DESC) g
    ON s.id = g.person_id;

4 个答案:

答案 0 :(得分:2)

我认为Postgre支持窗口函数,因此您应该可以执行类似

的操作
SELECT *
  FROM person p
  JOIN grades g ON grades.person_id = p.id
 WHERE row_number() OVER (PARTITION BY g.person_id ORDER BY g.date DESC) = 1

编辑:显然在where子句中不支持窗口函数(应该知道这个,因为它有意义)。然而,这不是一个无法解决的问题:

SELECT *
  FROM person p
  JOIN (SELECT person_id, <other_fields>, row_number() OVER (PARTITION BY person_id ORDER BY date DESC) AS rn FROM grades) g
 WHERE g.rn = 1

如果您的数据很大,请检查执行计划。

答案 1 :(得分:1)

虽然我不熟悉Postgres,但我在与Oracle合作时做了很多这样的事情。也许下面的查询会有所帮助。

select p.id,
       p.name,
       p.address,
       p.city,
       p.phone,
       g.date,
       g.test_name,
       g.grade 
from person p, 
     grades g
where p.id = g.person_id 
  and g.date = (select max(g2.date) 
                     from grades g2
                     where g2.id = g.id
                )

答案 2 :(得分:1)

是的,这是可能的。您正在寻找的条款是“DISTINCT ON”。有了它,您可以轻松地进行查询,而无需对同一个表进行子选择和多次扫描。

在文档中,请注意“DISTINCT ON”的 ON 部分。

答案 3 :(得分:0)

select 
S.id, 
S.name, 
S.address, 
S.city, 
S.phone, 
G.id as grade_id, 
G.date,
G.test_name,
G.grade

from
   Grades G,
   Student S, 
   (select S.id as studentid, max(date) as latest_grade_date  
    from student S , grades G where s.id = g.person_id) Q
WHERE
   G.person_id = Q.studentid
   AND S.id = Q.studentid
   AND G.date = Q.latest_grade_date
   AND S.id = G.person_id