簡體   English   中英

MySQL:選擇N行,但在一列中僅包含唯一值

[英]MySQL: Select N rows, but with only unique values in one column

給定此數據集:

ID  Name            City            Birthyear
1   Egon Spengler   New York        1957
2   Mac Taylor      New York        1955
3   Sarah Connor    Los Angeles     1959
4   Jean-Luc Picard La Barre        2305
5   Ellen Ripley    Nostromo        2092
6   James T. Kirk   Riverside       2233
7   Henry Jones     Chicago         1899

我需要找到3個最老的人,但每個城市只有一個。

如果它只是最老的三個,那將是...

  • 亨利·瓊斯/芝加哥
  • 麥克·泰勒(Mac Taylor)/紐約
  • 埃貢·斯賓格勒(Egon Spengler)/紐約

但是,由於Egon Spengler和Mac Taylor都位於紐約,因此Egon Spengler會退學,而下一個(Sarah Connor /洛杉磯)會進來。

有什么優雅的解決方案嗎?

更新:

當前,PConroy的一種變體是最好/最快的解決方案:

SELECT P.*, COUNT(*) AS ct
   FROM people P
   JOIN (SELECT MIN(Birthyear) AS Birthyear
              FROM people 
              GROUP by City) P2 ON P2.Birthyear = P.Birthyear
   GROUP BY P.City
   ORDER BY P.Birthyear ASC 
   LIMIT 10;

對於大數據集(5分鍾后終止),他最初的“ IN”查詢速度極慢,但是將子查詢移至JOIN可以大大加快速度。 大約花費了0.15秒。 在我的測試環境中為1 mio行。 我有一個關於“城市,出生年份”的索引,另一個是關於“出生年份”的索引。

注意:這與...有關

可能不是最優雅的解決方案,並且IN的性能可能在較大的表上受到影響。

嵌套查詢獲取每個城市的最小Birthyear 在外部查詢中,只有具有該Birthyear記錄才匹配。 按年齡排序,然后限制為3個結果,即可使您成為城市中年齡最大的3個年齡最大的人(Egon Spengler退學..)

SELECT Name, City, Birthyear, COUNT(*) AS ct
FROM table
WHERE Birthyear IN (SELECT MIN(Birthyear)
               FROM table
               GROUP by City)
GROUP BY City
ORDER BY Birthyear DESC LIMIT 3;

+-----------------+-------------+------+----+
| name            | city        | year | ct |
+-----------------+-------------+------+----+
| Henry Jones     | Chicago     | 1899 | 1  |
| Mac Taylor      | New York    | 1955 | 1  |
| Sarah Connor    | Los Angeles | 1959 | 1  |
+-----------------+-------------+------+----+

編輯 -在外部查詢中添加了GROUP BY City ,因為出生年份相同的人將返回多個值。 對外部查詢進行分組可確保每個城市僅返回一個結果,如果一個以上的最小Birthyear不止一個人。 ct欄將顯示該Birthyear所在城市中是否有一個以上的人

這可能不是最優雅,最快的解決方案,但它應該可以工作。 我期待看到真正的數據庫專家的解決方案。

select p.* from people p,
(select city, max(age) as mage from people group by city) t
where p.city = t.city and p.age = t.mage
order by p.age desc

這樣的事嗎?

SELECT
  Id, Name, City, Birthyear
FROM
  TheTable
WHERE
  Id IN (SELECT TOP 1 Id FROM TheTable i WHERE i.City = TheTable.City ORDER BY Birthyear)

不太漂亮,但也應該與具有相同dob的多個人一起工作:

測試數據:

select id, name, city, dob 
into people
from
(select 1 id,'Egon Spengler' name, 'New York' city , 1957 dob
union all select 2, 'Mac Taylor','New York', 1955
union all select 3, 'Sarah Connor','Los Angeles', 1959
union all select 4, 'Jean-Luc Picard','La Barre', 2305
union all select 5, 'Ellen Ripley','Nostromo', 2092
union all select 6, 'James T. Kirk','Riverside', 2233
union all select 7, 'Henry Jones','Chicago', 1899
union all select 8, 'Blah','New York', 1955) a

查詢:

select 
    * 
from 
    people p
    left join people p1
    ON 
        p.city = p1.city
        and (p.dob > p1.dob and p.id <> p1.id)
        or (p.dob = p1.dob and p.id > p1.id)
where
    p1.id is null
order by 
    p.dob

@布萊姆

UPDATED剛發現使用USING代替ON很好。 它將刪除結果中的重復列。

SELECT P.*, COUNT(*) AS ct
   FROM people P
   JOIN (SELECT City, MIN(Birthyear) AS Birthyear
              FROM people 
              GROUP by City) P2 USING(Birthyear, City)
   GROUP BY P.City
   ORDER BY P.Birthyear ASC 
   LIMIT 10;

原始郵件

嗨,我試圖使用您更新的查詢,但我得到錯誤的結果,直到我添加了要加入的額外條件(也在join select中添加了額外的列)。 轉移到您的查詢,我正在使用此:

SELECT P.*, COUNT(*) AS ct
   FROM people P
   JOIN (SELECT City, MIN(Birthyear) AS Birthyear
              FROM people 
              GROUP by City) P2 ON P2.Birthyear = P.Birthyear AND P2.City = P.City
   GROUP BY P.City
   ORDER BY P.Birthyear ASC 
   LIMIT 10;

從理論上講,您不需要最后一個GROUP BY P.City,但是為了防止萬一,我暫時將其保留在那里。 稍后可能會刪除它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM