2014-05-12 13 views
7

Z biegiem czasu przyzwyczaiłem się do niesamowicie przydatnej funkcjonalności połączeń toczenia data.table w r. Wykorzystują one operacje LOCF (ostatnia obserwacja przeniesiona do przodu). Niestety, jestem zmuszony pracować w środowisku, które jest mi mniej znane (używając postgres). Czy istnieje analogiczna operacja w SQL (szczególnie postgres)?Łączenia toczenia (LOCF) w PostgreSrze

Oto przykład tego, co mam i wyjście Chciałbym:

Oto moja pierwsza tabela

dt1 = data.table(Date=seq(from=as.Date("2013-01-03"), 
     to=as.Date("2013-06-27"), by="1 day"),key="Date")[, ind:=.I] 

      Date ind 
    1: 2013-01-03 1 
    2: 2013-01-04 2 
    3: 2013-01-05 3 
    4: 2013-01-06 4 
    5: 2013-01-07 5 
---    
172: 2013-06-23 172 
173: 2013-06-24 173 
174: 2013-06-25 174 
175: 2013-06-26 175 
176: 2013-06-27 176 

Oto mój drugi stół

dt2 = data.table(Date=seq(from=as.Date("2013-01-01"), 
     to=as.Date("2013-06-30"), by="1 week"),key="Date") 

      Date 
1: 2013-01-01 
2: 2013-01-08 
3: 2013-01-15 
4: 2013-01-22 
5: 2013-01-29 
--- 
22: 2013-05-28 
23: 2013-06-04 
24: 2013-06-11 
25: 2013-06-18 
26: 2013-06-25 

Oto kod użyłbym w data.table dla pożądanego wyjścia.

dt1[dt2, roll=Inf] 

      Date ind 
1: 2013-01-01 NA 
2: 2013-01-08 6 
3: 2013-01-15 13 
4: 2013-01-22 20 
5: 2013-01-29 27 
--- 
22: 2013-05-28 146 
23: 2013-06-04 153 
24: 2013-06-11 160 
25: 2013-06-18 167 
26: 2013-06-25 174 

Czy to w ogóle możliwe przy użyciu postgres (lub bardziej ogólnie rzecz biorąc, SQL? Dziękuję bardzo za wszelką pomoc można dostarczyć.

+0

Co zrobić wartości w kolumnie „ind " oznaczać? –

+0

Jest to po prostu wartość, aby potwierdzić, że połączenie jest wykonywane poprawnie. W tym przypadku zasadniczo oznacza numer wiersza. –

+0

Jeśli tylko potwierdza, że ​​sprzężenie jest wykonywane poprawnie, nie możesz po prostu użyć drugiej tabeli samodzielnie?Wartości w kolumnie "Data" są identyczne. –

Odpowiedz

3

Chciałbym być naprawdę zainteresowany, aby zobaczyć, czy ktoś może to zrobić bez . pierwszy wypełniania pełny przekrój dołącz tabelę ale tu jest rozwiązanie z krzyżem dołączyć:

http://sqlfiddle.com/#!2/b2f3f/3/0

Tworzenie schematu:

CREATE TABLE Table1 
    (`t1` double, `ind` int) 
; 

INSERT INTO Table1 
    (`t1`, `ind`) 
VALUES 
    (1, 1), 
    (1.9, 2), 
    (3.1, 3), 
    (4, 4), 
    (5.1, 5), 
    (5.9, 6) 
; 

CREATE TABLE Table2 
    (`t2` int) 
; 

INSERT INTO Table2 
    (`t2`) 
VALUES 
    (1), 
    (2), 
    (3), 
    (4), 
    (5), 
    (6) 
; 

Zapytanie:

select t2, max(ind) 
from (select t2, ind 
     from table1 
     cross join table2 
     where t1 <= t2) as foo 
group by t2 

Wynik:

T2 MAX(IND) 
1 1 
2 2 
3 2 
4 4 
5 4 
6 6 

EDIT: @ komentarz Hadley jest poprawna, że ​​pełny przekrój dołączyć tabelę nigdy nie zmaterializowanej pomocą kwerendy powyżej, jak wyżej zapytanie produkuje sami wyjaśnić i wyniki jak poniżej zapytania:

select t2, max(ind) 
from table1 
cross join table2 
where t1 <= t2 
group by t2 
+0

Jestem prawie pewna, że ​​postgres nigdy nie realizuje pełnego sprzężenia (krzyż jest w rzeczywistości domyślnym zachowaniem), ale chciałbyś to sprawdzić za pomocą wyjaśnienia (pod warunkiem, że ustawiłeś rozsądne indeksy). – hadley

+0

Wygląda na to, że to działa tutaj. Będę teraz próbował na moich znacznie większych zestawach danych, aby zobaczyć, jak się skaluje. Dzięki! –

+0

Czy to oznacza, że ​​pełna tabela łączenia krzyżowego nigdy nie jest wypełniona? –

2

sinc e Pracuję w specjalnym środowisku Postgres, najwyraźniej nie pozwala mi to na łączenie się. Bardzo dziękuję @Clayton Stanley za wspaniałą odpowiedź, ale musiałem spróbować innej trasy. Wygląda na to, że działa do tej pory. Przepraszam, że nie potrafię porównywać czasu obu metod.

Tworzenie schematu

CREATE TABLE Table1 
    (`id` int,`t1` double, `ind` int) 
; 

INSERT INTO Table1 
    (`id`,`t1`, `ind`) 
VALUES 
    (1,0.99, 5), 
    (1,1.90, 10), 
    (2,3.10, 12), 
    (2,4.00, 3), 
    (3,5.10, 8), 
    (3,5.90, 16), 
    (4,5.90, 7), 
    (4,5.99, 20) 
; 



CREATE TABLE Table2 
    (`id` int, `t2` double) 
; 

INSERT INTO Table2 
    (`id`,`t2`) 
VALUES 
    (1,1.00), 
    (2,3.95), 
    (3,5.05), 
    (4,6.01) 
; 

wykonaj przyłączyć za pomocą podzapytania

select B.* 
from Table2 as A 
join Table1 as B 
on B.id=A.id 
join(
    select 
     SUBB.id, 
     max(SUBB.t1) as t1 
    from Table2 as SUBA 
    join Table1 as SUBB 
    on SUBB.id=SUBA.id and 
    SUBB.t1 <= SUBA.t2 
    group by SUBB.id 
    ) 
as subqry 
on B.t1=subqry.t1 and 
    A.id=subqry.id 

przykładzie schematu i wyjścia jest tutaj:

Link to schema

Powiązane problemy