4

ソフトウェア パッケージの更新に関するメタデータのテーブルがあります。表には列がありますid, name, version。名前が特定の名前のリストの1つであり、バージョンがその名前のすべての行の最大であるすべての行を選択したい。

たとえば、次のレコードがあるとします。

+----+------+---------+
| id | name | version |
+----+------+---------+
| 1  | foo  | 1       |
| 2  | foo  | 2       |
| 3  | bar  | 4       |
| 4  | bar  | 5       |
+----+------+---------+

そして、タスク「レコード「foo」と「bar」の最新バージョンを教えてください。結果は次のようになります。

+----+------+---------+
| id | name | version |
+----+------+---------+
| 2  | foo  | 2       |
| 4  | bar  | 5       |
+----+------+---------+

私がこれまでに思いついたのは、ネストされたクエリを使用することです:

SELECT * 
  FROM updates 
  WHERE (
    id IN (SELECT id 
             FROM updates 
             WHERE name = 'foo' 
             ORDER BY version DESC 
             LIMIT 1)
  ) OR (
    id IN (SELECT id 
             FROM updates 
             WHERE name = 'bar' 
             ORDER BY version DESC 
             LIMIT 1)
  );

これは機能しますが、気分が悪いです。より多くの名前でフィルタリングしたい場合は、サブクエリ全体を複数回複製する必要があります。これを行うより良い方法はありますか?

4

3 に答える 3

5
select distinct on (name) id, name, version
from metadata
where name in ('foo', 'bar')
order by name, version desc
于 2013-04-20T11:43:46.003 に答える
3

NOT EXISTS不要な準最適タプルを回避する方法です。

SELECT * 
FROM updates uu
WHERE uu.zname IN ('foo', 'bar')
AND NOT EXISTS (
    SELECT *
    FROM updates nx
    WHERE nx.zname = uu.zanme
    AND nx.version > uu.version
    );

注:多かれ少なかれpostgresqlのキーワードであるため、に置き換えましnameた。zname

于 2013-04-20T11:44:29.567 に答える
2

Qを読み直した後の更新:

名前が指定された名前のリストの1つであり、バージョンがその名前のすべての行の最大であるすべての行選択したい。

同点 ( ごとに最大バージョンを持つ複数の行) が存在する可能性がある場合は、サブクエリでnameウィンドウ関数を使用できます。rank()PostgreSQL 8.4 以降が必要です。

SELECT *
FROM  (
   SELECT *, rank() OVER (PARTITION BY name ORDER BY version DESC) AS rnk
   FROM   updates 
   WHERE  name IN ('foo', 'bar')
   )
WHERE rnk = 1;
于 2013-04-20T11:48:15.050 に答える