2009-12-23 83 views
15

我正在尋找一種方法來處理以下情形。我有一個數據庫表,我需要爲表中包含的每個「組ID」只返回一條記錄,而且每個組中選擇的記錄應該是家中最老的人。SQL查詢每個組只返回1條記錄ID

ID Group ID Name    Age 
1 134  John Bowers  37 
2 134  Kerri Bowers  33 
3 135  John Bowers  44 
4 135  Shannon Bowers  42 

所以在上面提供的示例數據中,我需要ID 1和3返回,因爲它們是每個組ID中最老的人。

這是針對SQL Server 2005數據庫查詢的。

+0

如果你想要這個名字,如果你有> 1個年齡最大的人,你仍然有機會選擇> 1行。在這種情況下,你也應該建立標準名稱。 – 2009-12-23 17:36:26

+0

好點克里斯。是試圖簡化這個問題一點,但是留下這樣的漏洞:-)我其實有一個性別領域,所以我正在尋找選擇一個家庭中最老的男性。如果有男性,那麼最老的女性。如果同一家庭中有兩名男性同齡,那麼我只需要選擇其中的一項。這可以基於簡單的事情,就像打破決鬥者身份證號碼最低的人那樣簡單。 – 2009-12-23 17:50:59

+1

Joe Celko的優秀着作「SQL for Smarties」第21.4節「極值函數」中有一個很好的討論。如果你要碰到比簡單的SELECT和INSERT更棘手的事情,我強烈推薦本書。 – shoover 2009-12-23 18:05:09

回答

21
SELECT t.* 
FROM (
     SELECT DISTINCT groupid 
     FROM mytable 
     ) mo 
CROSS APPLY 
     (
     SELECT TOP 1 * 
     FROM mytable mi 
     WHERE mi.groupid = mo.groupid 
     ORDER BY 
       age DESC 
     ) t 

或本:

SELECT * 
FROM (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY groupid ORDER BY age DESC) rn 
     FROM mytable 
     ) 
WHERE rn = 1 

這甚至關係的情況下返回每組最多一個記錄。

對於這兩種方法的性能比較請參見這篇文章中我的博客:

+0

+1:是的,忘了我關於領帶的聲明。太忙的戰鬥火災。 – 2009-12-23 17:41:19

+0

感謝Quassnoi。我能夠將性別列添加到ORDER By子句的年齡列中,並獲得我期待的結果! (我的第一個問題後,性別專欄只在評論中討論)您的解決方案非常完美,適應性強! – 2009-12-23 17:57:14

+0

跟進問題。這些將以17500萬條記錄運行。其中一個或另一個查詢是否更高效? – 2009-12-23 18:00:43

0
SELECT GroupID, Name, Age 
FROM table 
INNER JOIN 
(
SELECT GroupID, MAX(Age) AS OLDEST 
FROM table 
) AS OLDESTPEOPLE 
ON 
table.GroupID = OLDESTPEOPLE.GroupID 
AND 
table.Age = OLDESTPEOPLE.OLDEST 
3

用途:

SELECT DISTINCT 
     t.groupid, 
     t.name 
    FROM TABLE t 
    JOIN (SELECT t.groupid, 
       MAX(t.age) 'max_age' 
      FROM TABLE t 
     GROUP BY t.groupid) x ON x.groupid = t.groupid 
          AND x.max_age = t.age 

那麼,如果有2+人一個組的同一年齡?存儲出生日期而不是年齡會更好 - 您可以始終計算出示日期的出生日期。

+0

小心領帶! – Quassnoi 2009-12-23 17:39:49

0

試試這個(假設集團是同義詞家用

Select * From Table t 
Where Age = (Select Max(Age) 
      From Table 
      Where GroupId = t.GroupId) 

如果有兩個或多個「最老」的人,一些家庭(他們都是相同年齡和有其他人沒有人老),那麼這將返回所有這些,而不是隨機一個。

如果這是一個問題,那麼您需要添加另一個子查詢以返回該集合中某個人的任意鍵值。

Select * From Table t 
Where Id = 
    (Select Max(Id) Fom Table 
    Where GroupId = t.GroupId 
     And Age = 
     (Select(Max(Age) From Table 
      Where GroupId = t.GroupId))