2016-03-28 8 views
0

Birden çok özellik tarafından mantıksal olarak gruplandırılabilen verileri barındıran bir tablom var (örneğin yabancı anahtar). Veriler sürekli zaman aralığı boyunca ardışıktır; yani bir zaman serisi verisidir. Elde etmeye çalıştığım şey, her grup grubu için yalnızca en yeni değerleri seçmek. İşte İlgili kayıtların grubu için en son değerleri seçin

örnek veridir:

+-----------------------------------------+ 
| 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   | 
+-----------------------------------------+ 

Ve burada istenen çıktı örneğidir:

+-----------------------------------------+ 
| 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   | 
+-----------------------------------------+ 

Bu perspektif koymak için - her ilgili nesne için ben son tarihiyle her kodu seçmek istiyorum .

İşte geldiğim bir seçimdi. Ben ROW_NUMBER OVER (PARTITION BY...) yaklaşım kullandım:

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) 

O inşaat ama sorun acı yavaş olmasıdır; Yaklaşık 3 milyon fundamentals kayıtlarına eşit olan üretim verilerinin yaklaşık% 5'i ile çalışırken bu seçimin tamamlanması yaklaşık 10 saniye sürmektedir. Tahminimce, önce büyük miktarlarda kayıt seçerek alt seçim yapılıyor.

Bu sorguyu hızlandırmanın herhangi bir yolu var mı, yoksa yanlış yoldan kazıyorum mı?

cevap

1

Postgres bu amaçla distinct on elverişli sunmaktadır:

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

Çok teşekkürler deneyebilirsiniz inanıyoruz! Düşündüğüm daha kolay oldu; Başlangıçta, en basit çözümle ilgilenen biraz fazla karmaşıklaştırdım. – Ruslan

0

Bu nedenle sorgunuz, örnek verilerinizden farklı sütun adları kullanmaktadır, bu yüzden söylemek zor, ancak yalnızca tarih hariç her şeyle gruplandırmak istediğiniz gibi görünüyor mu? Son zamanlarda birden çok tarihiniz olmadığı varsayıldığında, bunun gibi bir şey çalışmalıdır. Temel olarak pencere fonksiyonunu kullanmayın, uygun bir grup kullanın ve motorunuz sorguyu daha iyi optimize etmelidir.

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

Diğer seçenek:

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 

Bu hiç tarafından bölüm ne için en iyi değeri döndürecektir ve ne olursa olsun sipariş tarafından.

0

Ben böyle bir şey

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

    GROUP BY CODE,Relation_ID,Date 
İlgili konular