2010-01-27 40 views
4

我有兩個表:選擇*最新*等級信息爲每一個學生

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 

任何幫助將不勝感激,謝謝。

編輯:加入溶液QUERY

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; 

回答

1

是的,這是可能的。您正在尋找的條款是「DISTINCT ON」。使用它,您可以輕鬆地進行查詢,而無需對同一張表進行子查詢和多次掃描。

在文檔中,請注意ON部分「DISTINCT ON」。

+0

這一個實際上對我很好。我在問題結尾處發佈瞭解決方案查詢。其他一些雙查詢解決方案花費了大約20多秒。嘗試DISTINCT ON方法後,我把它降到3+秒以上。 我的'成績表'實際上有50,000多行。 – PKKid 2010-01-28 21:27:46

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 

檢查執行計劃,但是,如果您的數據很大。

+0

是的,自v8.4開始支持窗口功能。 – bernie 2010-01-27 23:00:34

+0

不幸的是,這不適合我。 「WHERE子句中不支持窗口函數」。 – PKKid 2010-01-28 20:45:59

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 
+0

但是,另一種方式看起來更好 – 2010-01-27 23:05:10

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 
       ) 
+0

這個工作,但需要20秒,這可能不是一個偉大的Web應用程序。我正在查看我的索引,看看我是否錯過了一些東西。 :) – PKKid 2010-01-28 20:54:50

+0

@PKKid - 我看到depesz的DISTINCT ON解決方案爲你工作,並且更快。不過,我很想知道,如果通過一些創造性索引甚至可以使3秒鐘的執行速度更快。我可能不得不在下一個個人項目中給Postgres一個嘗試。 DISTINCT ON是一個很好的功能。 – ssakl 2010-01-29 14:30:10

相關問題