Таблица соединения SQL и результат сопоставления с ограничивающим условием - PullRequest
1 голос
/ 29 сентября 2019

У меня есть таблица курсов и транзакций, по которой я хочу узнать курс обмена на основе последнего обновленного курса валюты (относится к отметке времени транзакции)

Table - rates
('2018-04-01 00:00:00', 'EUR', 'RUB', '1.71'),
('2018-04-01 01:00:05', 'EUR', 'RUB', '1.82'),
('2018-04-01 00:00:00', 'USD', 'RUB', '0.71'),
('2018-04-01 00:00:05', 'USD', 'RUB', '0.82'),
('2018-04-01 00:01:00', 'USD', 'RUB', '0.92'),
('2018-04-01 01:02:00', 'USD', 'RUB', '0.62'),

Table - transactions
('2018-04-01 00:00:00', 1, 'EUR', 2.45),
('2018-04-01 01:00:00', 1, 'EUR', 8.45),
('2018-04-01 01:30:00', 1, 'USD', 3.5),

Моя попытка ограничить эти дополнительные данные

select * from transactions tr1 
left outer join rates ex1 
             on tr1.ts >= ex1.ts 
                and tr1.currency = ex1.from_currency;

Результат, который я получаю, содержит все обновления обменного курса, которые произошли ранее 2

2018-04-01 00:00:00 1   EUR 2.45    2018-04-01 00:00:00 EUR RUB 1.71 (correct)
2018-04-01 01:00:00 1   EUR 8.45    2018-04-01 00:00:00 EUR RUB 1.71 (correct)
2018-04-01 01:30:00 1   USD 3.5     2018-04-01 01:02:00 USD RUB 0.62 (only this should remain)
2018-04-01 01:30:00 1   USD 3.5     2018-04-01 00:01:00 USD RUB 0.92
2018-04-01 01:30:00 1   USD 3.5     2018-04-01 00:00:05 USD RUB 0.82
2018-04-01 01:30:00 1   USD 3.5     2018-04-01 00:00:00 USD RUB 0.71 

Я пытался определить свое собственное утверждение (мой предыдущий запрос):

where ex1.ts = (select max(ex2.ts) from rates ex2 
                where ex2.from_currency=ex1.from_currency 
                      and ex2.to_currency=ex1.from_currency);

Но это ничего не возвращает ...

Ответы [ 2 ]

1 голос
/ 29 сентября 2019

Вы можете решить это с помощью оконных / аналитических функций.В разделе мы упорядочиваем по ex1.ts в порядке убывания, чтобы получить скорость, ближайшую к отметке времени транзакции ts.Условие tr1.ts >= ex.ts в Присоединении гарантирует, что мы получаем только обменные курсы в или до времени транзакции.

select dt.* 
from 
(
select tr1.*, ex1.*, 
       row_number() over (partition by ex1.from_currency order by ex1.ts desc) as rn
from transactions tr1 
left outer join exchange_rates ex1 
             on tr1.ts >= ex1.ts 
                and tr1.currency = ex1.from_currency
) as dt 
where dt.rn = 1
1 голос
/ 29 сентября 2019

Postgres имеет очень удобный distinct on для получения одного ряда на группу.Это должно делать то, что вы хотите:

select t.*, r.*
from transactions t left join
     (select distinct on (from_currency, to_currency) r.*
      from rates r
      order by from_currency, to_currency, ts desc
     ) r
     on r.from_currency = t.currency and
        r.to_currency = 'RUB';

РЕДАКТИРОВАТЬ:

Если вы хотите, чтобы последняя дата для каждой транзакции, а затем использовать боковое соединение:

select t.*, r.*
from transactions t left join lateral
     (select r.*
      from rates r
      where r.from_currency = t.currency and
            r.ts <= t.ts
      order by r.ts desc
      limit 1
     ) r
     on 1=1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...