如何链接两个表,但只从PostgreSQL中的一个表中获取MAX值?

时间:2018-06-07 17:54:25

标签: sql postgresql greatest-n-per-group postgres-9.6

我有两张桌子

exchange_rates
TIMESTAMP             curr1    curr2    rate
2018-04-01 00:00:00   EUR      GBP      0.89
2018-04-01 01:30:00   EUR      GBP      0.92
2018-04-01 01:20:00   USD      GBP      1.23

transactions
TIMESTAMP             user    curr    amount
2018-04-01 18:00:00   1       EUR     23.12
2018-04-01 14:00:00   1       USD     15.00
2018-04-01 01:00:00   2       EUR     55.00

我想以下列方式将1. currency和2. TIMESTAMP上的这两个表链接起来:

    curr中的
  • transactions必须等于curr1
  • 中的exchange_rates TIMESTAMP中的
  • exchange_rates必须小于或等于TIMESTAMP中的transactions(因此我们只提取交易时相关的汇率)

我有这个:

SELECT
trans.TIMESTAMP, trans.user,
-- Multiply the amount in transactions by the corresponding rate in exchange_rates
trans.amount * er.rate AS "Converted Amount"
FROM transactions trans, exchange_rates er
WHERE trans.curr = er.curr1
AND er.TIMESTAMP <= trans.TIMESTAMP
ORDER BY trans.user

但这是两个结果的链接,因为输出的行数多于transactions中的行数。

期望的输出:

TIMESTAMP             user    Converted Amount
2018-04-01 18:00:00   1       21.27
2018-04-01 14:00:00   1       18.45
2018-04-01 01:00:00   2       48.95

Converted Amount

背后的逻辑
  • 第1行:用户在18:00消费,因此rate的{​​{1}}小于或等于TIMESTAMP exchange_rates,即01:30的EUR为0.92
  • 第2行:用户在14:00消费,因此rate的{​​{1}}小于或等于TIMESTAMP exchange_rates,即01:20,美元为1.23
  • 第3行:用户在01:00消费,因此rate的{​​{1}}小于或等于TIMESTAMP中的exchange_rates,即00:00的EUR为0.89

如何在postgresql 9.6中执行此操作

1 个答案:

答案 0 :(得分:4)

您可以使用LATERAL JOIN(交叉申请)并将结果限制在符合条件的第一行。

select t.dt, t.usr, t.amount * e.rate as conv_amount
from   transactions t
join lateral (select *
              from   exchange_rates er
              where  t.curr = er.curr1
              and    er.dt <= t.dt
              order by dt desc
              limit 1) e on true;
dt                  | usr | conv_amount
:------------------ | --: | ----------:
2018-04-01 18:00:00 |   1 |     21.2704
2018-04-01 14:00:00 |   1 |     18.4500
2018-04-01 01:00:00 |   2 |     48.9500

db&lt;&gt;小提琴here