34

このデータセットを考えると:

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 人の最年長者を見つける必要がありますが、すべての都市で 1 人だけです。

最年長の3人だけなら…

  • ヘンリー・ジョーンズ / シカゴ
  • マック・テイラー / ニューヨーク
  • エゴン・スペングラー / ニューヨーク

しかし、Egon Spengler と Mac Taylor はどちらもニューヨークにいるため、Egon Spengler はドロップアウトし、代わりに次のメンバー (Sarah Connor / Los Angeles) が入ってきます。

エレガントなソリューションはありますか?

アップデート:

現在、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;

「IN」を使用した彼の元のクエリは、大きなデータセットでは非常に遅くなります (5 分後に中止されます) が、サブクエリを JOIN に移動すると、大幅に高速化されます。約0.15秒かかりました。テスト環境で 100 万行。「都市、誕生年」のインデックスと、「誕生年」だけのインデックスがあります。

注:これは関連しています...

4

5 に答える 5

18

おそらく最も洗練されたソリューションではなく、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-同じ出生年の人は複数の値を返すため、外部クエリに追加されます。外側のクエリでグループ化すると、複数の人がその最小値を持っている場合、都市ごとに1つの結果のみが返されるようになりますBirthyearct列には、その都市に複数の人が存在するかどうかが表示されますBirthyear

于 2008-10-10T10:39:20.420 に答える
3

これはおそらく最もエレガントで最速のソリューションではありませんが、機能するはずです。私は実際のデータベースの達人の解決策を見るのを楽しみにしています。

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
于 2008-10-10T10:38:17.367 に答える
2

そんな感じ?

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)
于 2008-10-10T10:26:02.180 に答える
1

きれいではありませんが、同じ名前を持つ複数の人でも動作するはずです:

テストデータ:

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
于 2008-10-10T11:22:08.307 に答える
1

@ブラム

UPDATED は、ON の代わりに USING を使用するのが良いことを発見しました。結果の重複する列が削除されます。

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;

元の投稿

こんにちは、更新されたクエリを使用しようとしましたが、結合するための追加条件を追加するまで間違った結果が得られました (結合選択への追加列も)。あなたのクエリに転送され、私はこれを使用しています:

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 は必要ないはずですが、念のため、ここでは残しておきます。おそらく後で削除します。

于 2010-08-14T16:57:46.203 に答える