1

かなり一般的なパターンがあると思われるクエリがあります。次の表を検討してください。

id | val | ts
---+-----+-------
 a |  10 | 12:01
 a |  12 | 12:05
 a |   9 | 12:15
 b |  30 | 12:03

各IDのタイムスタンプで最新の値を取得したい。あなたがそれを行うことができるいくつかの方法:

-- where in aggregate subquery
-- we avoid this because it's slow for our purposes
select
  id, val
from t
where (id, ts) in
  (select
    id,
    max(ts)
   from t
   group by id);

-- analytic ranking
select
  id, val
from
  (select
    row_number() over (partition by id order by ts desc) as rank,
    id,
    val
  from t) ranked
where rank = 1;

-- distincting analytic
-- distinct effectively dedupes the rows that end up with same values
select
  distinct id, val
from
  (select
    id,
    first_value(val) over (partition by id order by ts desc) as val
  from t) ranked;

分析ランキング クエリは、効率的なクエリ プランを考え出すのが最も簡単なクエリのように感じます。しかし、審美的にも保守的にも、かなり醜いです (特に、テーブルに複数の値列がある場合)。本番環境のいくつかの場所では、パフォーマンスが同等であることがテストで示された場合に、個別の分析クエリを使用します。

このような醜いクエリに終わらずに、rank = 1 のようなことを行う方法はありますか?

4

2 に答える 2

1

これは最も簡単で最速です:

select distinct on (id)
    id, ts, val
from t
order by id, ts desc

( distinc onPostgresql のみ) は、各 ID に対して 1 つの行のみを返します。あなたorder byがどちらをコントロールするかで。この場合、最後のts. distinct on中間ステップを必要とせずに、必要な数の列を結果セットに含めることができます。で使用される列は、distinct on最初に に含める必要がありますorder by

于 2013-06-06T11:36:39.070 に答える