2011-03-22 64 views
3

我只是想知道最新的記錄,如果以下兩個SQL語句有任何性能差異或者是他們本質上是相同的:選擇每人

spouse表中選擇一個人的最新配偶記錄(爲person_id,spouse_id, marriage_date)。

select * 
from spouse 
where (person_id, marriage_date) in (select person_id, max(marriage_date) 
             from spouse 
             group by person_id 
            ) 

select * 
from spouse s1 
where marriage_date = (select max(marriage_date) 
         from spouse s2 
         where s1.person_id = s2.person_id 
        ) 

這是報告一個共同的要求,例如,員工的工作最新,最高的教育等等等等,我想知道如果你喜歡上述表述過的一種方式其他以及爲什麼,或者如果還有其他更好的方法(在性能/可讀性方面)去了解這些獲取最新/最大的需求。

+0

如果'person_id + marriage_date'不應該是唯一的 - 那麼你可能會得到錯誤的數據(如果某人已經在一天內結婚兩次;-))你的查詢不好 - – zerkms 2011-03-22 07:22:31

+0

,避免在日期/時間字段進行比較。有很多與此相關的潛在時間炸彈,你可以谷歌。 – 2011-03-22 08:44:24

+1

@Stephen - drivel。這就像說要避免編寫C#以防萬一你犯了一個錯誤。 – 2011-03-22 08:48:27

回答

1

您可以使用分析功能來做到這一點:

SELECT * 
    FROM (SELECT ROW_NUMBER() OVER (PARTITION BY person_id 
            ORDER BY marriage_date DESC) AS r, 
       t.* 
      FROM spouse t) x 
WHERE x.r = 1 

而且你可以通過看他們的執行計劃比較所有查詢的效率。

+0

Downvote刪除。 – 2011-03-22 09:18:56

3

正如在前面的回答已經提到,您可以使用SQL server windowing functions實現這一相當不錯。

SELECT s1.person_id, s1.marriage_date 
FROM spouse s1 
JOIN ( 
    SELECT 
     person_id, 
     ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY marriage_date DESC) AS Priority 
     FROM spouse 
    ) s2 
ON s2.person_id = s1.person_id AND s2.Priority = 1 

在連接查詢,我們通過person_id分區中的數據,然後應用排名函數(ROW_NUMBER()),其一個號分配給每一行,以降序的順序marriage_date。排名是每個person_id獨立完成的,所以連接條件s2.Priority = 1意味着我們得到的只是記錄與最大marriage_date每個人。

您可能會發現下面的有用:

0

你的例子是語法上是相同的。作爲一個經驗法則,用在當子查詢是最限制(即省去了大量的從結果集中的記錄),並使用相關子查詢,當外部查詢是最限制(即子查詢有超過總數紀錄結果集)。

基於表的統計和估算成本,甲骨文查詢優化器可能會重寫IN子句的相關子查詢,反之亦然。看看你的情況的解釋計劃,並以最低的成本選擇計劃。