2011-10-04 35 views
2

假設如下表/數據:如何在MySQL中使用MAX?

person_id age gender name 
1   25 Female Jane 
2   28 Male John 
3   29 Female Jill 
4   24 Male Jack 

如何查詢最古老的男性和女性?

這不是工作:SELECT person_id, max(age), gender, name FROM person GROUP BY gender

因爲它返回:

person_id age gender name 
2   28 Male John 
1   29 Female Jane 

期望的結果是:

person_id age gender name 
2   28 Male John 
3   29 Female Jill 

這有什麼錯我的SQL?

+0

集團按性別將性別的名字,並獲得最大的年齡了同桌,不合並結果 –

+0

Topener,我該如何查詢這個? – StackOverflowNewbie

+0

看看下面的答案,我認爲unbutbu在一分鐘內給你一個很好的例子 –

回答

3

你可以得到一個排結合ORDER BYLIMIT 1的所有數據。在你的情況下,使用此兩次,並用UNION結合:

(SELECT * 
    FROM person 
    WHERE gender = 'Male' 
    ORDER BY age DESC 
    LIMIT 1 
) 
UNION ALL 
    (SELECT * 
    FROM person 
    WHERE gender = 'Female' 
    ORDER BY age DESC 
    LIMIT 1 
) 

另一種方法是FING男性和女性(與子查詢)的最高年齡:如果您有更多的

SELECT * 
FROM person 
WHERE (gender = 'Male' 
     AND age = 
      (SELECT MAX(age) 
      FROM person 
      WHERE gender = 'Male' 
     ) 
    ) 
    OR (gender = 'Female' 
     AND age = 
      (SELECT MAX(age) 
      FROM person 
      WHERE gender = 'Female' 
     ) 
    ) 

如果您不想在查詢中硬編碼MaleFemale常數,則可以將其重寫爲:

SELECT p.* 
FROM person AS p 
    JOIN 
     (SELECT gender 
      , MAX(age) AS maxage 
     FROM person 
     GROUP BY gender 
    ) AS pg 
    ON pg.gender = p.gender 
    AND pg.maxage = p.age 

以上查詢有一個主要區別。第一次只會給你一個男性和一個女性的結果(最多)。第二次和第三次查詢會給你不止一個,當有許多(男性)具有相同的最大年齡,女性也是如此。

(gender, age)上的索引將有助於查詢。

+0

您展示的最後一個示例 - 與派生表聯接 - 就是我通常期望看到完成的方式。你列出的其他方法是可行的,但不會是我的第一選擇。 – Lee

+0

是的,我也使用3以上的2。查詢1具有不同的結果集,如果需要結果集(每個組只有一行),則可以將其更改爲更一般的結果集(如2-> 3更改)。 –

1

您需要先添加ORDER BY age DESC,因爲分組會將第一個元素傳遞。

(我想你甚至可以通過age與替換max(age)

+0

Manhim,你能給我完整的查詢嗎?只需將其添加到最後?這不適合我。我不明白爲什麼我需要訂購任何東西。我只想要最古老的男性和女性。我並不特別在乎結果的順序是什麼。 – StackOverflowNewbie

+0

'SELECT * FROM person ORDER BY age DESC GROUP BY gender''可能需要切換GROUP和ORDER,我不記得了。 – Manhim

3

當你GROUP BY性別,你不能選擇從每組值非聚合列(age彙總控制,但name是沒有):

the docs

MySQL extends the use of GROUP BY so that the select list can refer to 
nonaggregated columns not named in the GROUP BY clause.... The server is free 
to choose any value from each group, so unless they are the same, the values 
chosen are indeterminate. 

這是可能的,但是,要獲得期望的結果與subselec T:

SELECT p1.* 
FROM person p1 
INNER JOIN (
    SELECT gender,MAX(age) as age 
    FROM person 
    GROUP BY gender) as p2 
ON p1.gender = p2.gender AND p1.age = p2.age 
+0

unutbu,有什麼建議來獲取我需要的數據? – StackOverflowNewbie

+0

順便說一下,我給出的例子是我的問題的簡化版本。真正的問題是,我的數據庫中有一個特定的實體用於創建日誌條目。我需要找到該實體的最後一個日誌條目。我在表格中有一個時間戳列。 – StackOverflowNewbie

+0

您在此處顯示的查詢效率極低。即使最後一個查詢只返回幾行,數據庫也必須爲每個「person」中的行執行子選擇(使用隱式分組)。更好的方法(具有相同的結果)是@ ypercube答案中顯示的第三個查詢。 – Lee

0

您的評論說:

By the way, the example I gave is a simplified version of my problem. The real 
problem is that I have a certain entity in my database that makes log entries. I 
need to find the very last log entry for that entity. I have a timestamp column 
in the table 

嘗試以下,應該在我想象你有工作表中...但是提供的表結構,將有助於它可以用一組由太:)

來解決
select * from log_table 
where log_date_time = (select max(log_date_time) from log_table)