2016-03-28 10 views
0

複数のプロパティ(たとえば外部キーなど)で論理的にグループ化できるデータを格納するテーブルがあります。データは連続した時間間隔で連続しています。すなわち時系列データである。私が達成しようとしているのは、グループのグループごとに最新の値だけを選択することです。ここで関連レコードのグループの最新値を選択

はサンプルデータです:

+-----------------------------------------+ 
| code | value | date  | relation_id | 
+-----------------------------------------+ 
| A | 1  | 01.01.2016 | 1   | 
| A | 2  | 02.01.2016 | 1   | 
| A | 3  | 03.01.2016 | 1   | 
| A | 4  | 01.01.2016 | 2   | 
| A | 5  | 02.01.2016 | 2   | 
| A | 6  | 03.01.2016 | 2   | 
| B | 1  | 01.01.2016 | 1   | 
| B | 2  | 02.01.2016 | 1   | 
| B | 3  | 03.01.2016 | 1   | 
| B | 4  | 01.01.2016 | 2   | 
| B | 5  | 02.01.2016 | 2   | 
| B | 6  | 03.01.2016 | 2   | 
+-----------------------------------------+ 

そしてここでは、所望の出力の例です:

+-----------------------------------------+ 
| code | value | date  | relation_id | 
+-----------------------------------------+ 
| A | 3  | 03.01.2016 | 1   | 
| A | 6  | 03.01.2016 | 2   | 
| B | 3  | 03.01.2016 | 1   | 
| B | 6  | 03.01.2016 | 2   | 
+-----------------------------------------+ 

視点でこれを配置するには - すべての関連オブジェクトに対して私は、最新の日付を持つ各コードを選択します。

ここには、私が来たものがあります。それは動作しますが、問題は、それは痛々しいほど遅いことである

SELECT indicators.code, indicators.dimension, indicators.unit, x.value, x.date, x.ticker, x.name 
FROM (
    SELECT 
    ROW_NUMBER() OVER (PARTITION BY indicator_id ORDER BY date DESC) AS r, 
    t.indicator_id, t.value, t.date, t.company_id, companies.sic_id, 
    companies.ticker, companies.name 
    FROM fundamentals t 
    INNER JOIN companies on companies.id = t.company_id 
    WHERE companies.sic_id = 89 
) x 
INNER JOIN indicators on indicators.id = x.indicator_id 
WHERE x.r <= (SELECT count(*) FROM companies where sic_id = 89) 

;:私はROW_NUMBER OVER (PARTITION BY...)アプローチを使用しました約3百万に相当する生産データの約5%で作業する場合、fundamentalsレコードを選択するには、この選択に約10秒かかります。私の推測は、まず大量のレコードを選択する副選択のために起こることです。

このクエリを高速化する方法はありますか、それとも私がやっているように間違った方向に掘り下げていますか?

答えて

1

Postgresは、この目的のためにdistinct on便利を提供しています:

select distinct on (relation_id, code) t.* 
from t 
order by relation_id, code, date desc; 
+0

おかげで多くのことを試すことができると信じて!私は思ったより簡単でした。私は最初にそれを単純化して、最も簡単な解決策を見落としました。 – Ruslan

0

クエリではサンプルデータとは異なる列名が使用されるため、わかりにくいですが、日付以外のすべてをグループ化したいと思うようですか?あなたが複数の最新の日付を持っていないと仮定すると、このようなものはうまくいくはずです。基本的にウィンドウ関数を使用せずに、適切なグループを使用すると、エンジンはクエリをよりよく最適化する必要があります。

SELECT mytable.code, 
     mytable.value, 
     mytable.date, 
     mytable.relation_id 
    FROM mytable 
    JOIN (
     SELECT code, 
       max(date) as date, 
       relation_id 
      FROM mytable 
     GROUP BY code, relation_id 
     ) Q1 
    ON Q1.code = mytable.code 
    AND Q1.date = mytable.date 
    AND Q1.relation_id = mytable.relation_id 
0

その他のオプション:

SELECT DISTINCT Code, 
Relation_ID, 
FIRST_VALUE(Value) OVER (PARTITION BY Code, Relation_ID ORDER BY Date DESC) Value, 
FIRST_VALUE(Date) OVER (PARTITION BY Code, Relation_ID ORDER BY Date DESC) Date 
FROM mytable 

これは今まであなたがして、パーティション何のために、トップ値を返します、そして何のためにご注文。

0

は、私たちはこのような何か

SELECT CODE,Relation_ID,Date,MAX(value)value FROM mytable 

    GROUP BY CODE,Relation_ID,Date 
関連する問題