如何在 PostgreSQL 中 link 两个 table 但只从一个 table 中取最大值?
How to link two tables but only take the MAX value from one table in PostgreSQL?
我有两张桌子
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
我想link 1. currency 和2. TIMESTAMP 上的这两个表按以下方式:
curr
in transactions
必须等于 curr1
in exchange_rates
TIMESTAMP
in exchange_rates
必须小于或等于 TIMESTAMP
in 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
但这是 link 两个结果,因为输出的行比 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
小于或等于 exchange_rates
中的 TIMESTAMP
,即 0.92 欧元在 01:30
- 第 2 行:用户在 14:00 花费,所以取
rate
小于或等于 exchange_rates
中的 TIMESTAMP
,即 1.23 美元在 01:20
- 第 3 行:用户在 01:00 花费,所以取
rate
小于或等于 exchange_rates
中的 TIMESTAMP
,即 0.89 欧元在 00:00
如何在 postgresql 9.6 中执行此操作?
您可以使用 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<>fiddle here
我有两张桌子
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
我想link 1. currency 和2. TIMESTAMP 上的这两个表按以下方式:
curr
intransactions
必须等于curr1
inexchange_rates
TIMESTAMP
inexchange_rates
必须小于或等于TIMESTAMP
intransactions
(所以我们只提取当时相关的汇率交易)
我有这个:
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
但这是 link 两个结果,因为输出的行比 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
小于或等于exchange_rates
中的TIMESTAMP
,即 0.92 欧元在 01:30 - 第 2 行:用户在 14:00 花费,所以取
rate
小于或等于exchange_rates
中的TIMESTAMP
,即 1.23 美元在 01:20 - 第 3 行:用户在 01:00 花费,所以取
rate
小于或等于exchange_rates
中的TIMESTAMP
,即 0.89 欧元在 00:00
如何在 postgresql 9.6 中执行此操作?
您可以使用 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<>fiddle here