2014-03-29 81 views
0

必須是一個相當常見的任務,但我找不到一個優雅的方式來做到這一點。SQL檢索最新的行

表:

Id 
testdate 
partid 
testid 

相同的部分可在相同的測試多次經歷。我想要在(partlist)中的所有部分完成所有測試的最新結果。

SELECT max(testdate) 
FROM table 
WHERE partid IN (partlist) 
GROUP BY testid, partid 

幾乎可以完成這項工作,只是它沒有給我所需的id字段。我可以先選擇正確的日期,然後使用WHERE子句中的testdate,partid和testid選擇id字段,但這很醜陋。

必須有更好的方法來做到這一點?

如果需要,我願意放棄部分列表並只獲取一個部分的數據。

+2

您正在使用什麼RDBMS? –

+0

我使用ms sql,但是任何SQL都應該足以回答這個問題。如果它不是一些非常晦澀的功能,翻譯你的當地方言通常很容易。 – Bastiaan

回答

1

有優雅。然後有效率。在優雅方面,row_number()功能可以提供幫助。

在效率方面,not exists方法似乎在許多數據庫中很好地工作:

SELECT t.* 
FROM table t 
WHERE partid IN (partlist) AND 
     NOT EXISTS (SELECT 1 
        FROM table t2 
        WHERE t2.testid = t.testid and t2.partid = t.partid and 
         t2.testdate > t.testdate 
       ); 

它是說:「給我表中的所有行那裏沒有其他行具有相同的testidpartid,但有一個更大的testdate。「

+0

真棒,完美的作品!被SELECT 1 FROM ...部分推遲了一秒鐘。但現在我明白了,它只是選擇任何東西,一個虛擬的,如果WHERE子句沒有完成,它將不會得到任何結果,甚至不是「1」。 (以防別人遇到同樣的問題) – Bastiaan

+0

其次,我很驚訝它是高效的。現在我們爲表格的每一行檢查整個表格一遍又一遍?但它在我的1.4TB桌子上工作,所以它不是那麼糟糕。 – Bastiaan

1

你不說出你的DBMS,所以這是ANSI SQL:

select id, 
     max_testdate, 
     partid, 
     testid 
from (
    select Id, 
     testdate, 
     max(testdate) over (partition by testid, partid) as max_testdate 
     partid 
     testid 
    from the_table 
) t 
where testdate = max_testdate 
+0

這實際上也起作用。我不得不將它包裝在額外的「SELECT * FROM(..)」中,以防止在ms sql中出現錯誤「無效的列名'max_testdate'」。感謝您向我介紹OVER(PARTITION BY ..)子句。 – Bastiaan