从Exchange Rate表隐式计算SQL中的汇率

问题描述 投票:0回答:2

我有一个数据表,收入多种货币(让我们称之为TRANSACTION_TABLE,列如下:

TRANSACTION_NAME
TRANSACTION_VALUE
CURRENCY

,以及另一个包含汇率的表格(EXCHANGE_RATE):

FROM_CURRENCY (e.g. JPY)
TO_CURRENCY (e.g. USD)
EXCHANGE_RATE (x)

该表至少每种货币都转换为美元,但非美元TO_CURRENCY值的汇率并非详尽无遗。

我想要实现的是一个查询,它将交易转换为任何货币,即使未在EXCHANGE_RATE表中明确规定,通过将货币首先转换为美元,然后从美元转换为目标货币。

例如。 1000日元兑换英镑:

  1. 查找率JPY到USD - 计算= 1000 * EXCHANGE_RATE = 9
  2. 查找汇率GBP到USD - 计算= 9 \ EXCHANGE_RATE = 7

目前,我已经在TRANSACTION_TABLE上为EXCHANGE_RATE做了一个左联盟,但是我在接下来要去的地方迷路了。

任何帮助将不胜感激。

我到目前为止构建的查询(非常基本)如下,我是一个新手SQL用户。我首先建立了这个查询以转换为美元,这可以正常工作(因为我的汇率表包含所有货币对美元的价值) - 但是当将目标货币设置为GBP时它显然会失败,因为它只会返回空值。

SELECT TRANSACTION_NAME,
             SUM (TRANSACTION_VALUE * EXCHANGE_RATE)
                 AS "REVENUE GBP"
        FROM TRANSACTION_TABLE S
             LEFT JOIN EXCHANGE_RATE C ON S.CURRENCY = C.FROM_CURRENCY AND C.TO_CURRENCY = 'GBP'
ORDER BY TRANSACTION_NAME
sql oracle currency-exchange-rates
2个回答
3
投票

如果您的EXCHANGE_RATE表格对美元无穷无尽,那么您的转换将不会超过两次“跳跃”。最多,您将转换为美元,然后从美元转换为任何美元。鉴于此,我只会为所有可能的情况编码,而不是像CONNECT BY那样尝试一些奇特的东西。

我认为“所有可能的情况”是:

  • 该交易已经是目标货币
  • 交易采用可直接兑换为目标货币的货币
  • 交易必须转换为美元,然后从美元转换为目标货币。

这是一个将执行此操作的查询。 WITH条款只是为了给它一些数据 - 它们不会成为你解决方案的一部分,因为你有实际的表格。

WITH rates ( from_currency, to_currency, exchange_rate ) AS 
( SELECT 'JPY', 'USD', 0.009 FROM DUAL UNION ALL
  SELECT 'GBP', 'USD', 1.31 FROM DUAL UNION ALL
  SELECT 'CNY', 'USD', 0.15 FROM DUAL UNION ALL
  SELECT 'JPY', 'CNY', 0.06 FROM DUAL),
txns ( transaction_name, transaction_value, currency ) AS
 ( SELECT 'txn 1 in JPY', 1000, 'JPY' FROM DUAL UNION ALL
   SELECT 'txn 2 in GBP', 1000, 'GBP' FROM DUAL UNION ALL
   SELECT 'txn 3 IN CNY', 1000, 'CNY' FROM DUAL UNION ALL
   SELECT 'txn 4 IN unknown', 1000, 'XXX' FROM DUAL),
params ( target_currency ) AS 
 ( SELECT 'CNY' FROM DUAL )
SELECT t.transaction_name,
       t.transaction_value base_value,
       t.currency base_currency,
       t.transaction_value * CASE WHEN t.currency = params.target_currency THEN 1
            WHEN r1.from_currency IS NOT NULL THEN r1.exchange_rate
            ELSE r2usd.exchange_rate / r2tar.exchange_rate END converted_value,
        params.target_currency converted_currency
FROM   params CROSS JOIN 
       txns t 
       LEFT JOIN rates r1 ON r1.from_currency = t.currency AND r1.to_currency = params.target_currency
       LEFT JOIN rates r2usd ON r2usd.from_currency = t.currency AND r2usd.to_currency = 'USD'
       LEFT JOIN rates r2tar ON r2tar.from_currency = params.target_currency AND r2tar.to_currency = 'USD'

2
投票

我建议采取额外措施,使用UDS作为转移货币,使用额外定义的汇率扩展您的兑换表。

此查询添加通过USD计算的新费率。这是一个简单的内连接约束,因此计算是通过'USD'和from和to货币不同。 WHERE条款限制了已知的组合。

select  er1.FROM_CURRENCY, er2.TO_CURRENCY,  er1.EXCHANGE_RATE * er2.EXCHANGE_RATE EXCHANGE_RATE
from exchange_rates er1
join exchange_rates er2
on er1.TO_CURRENCY = 'USD' and er2.FROM_CURRENCY = 'USD'  and er1.FROM_CURRENCY != er2.TO_CURRENCY
where (er1.FROM_CURRENCY, er2.TO_CURRENCY)
not in (select FROM_CURRENCY,   TO_CURRENCY from exchange_rates)

您可以定义物理新表或视图,甚至仅将其作为子查询执行,作为原始表的UNION ALL和此查询的结果。

您的最终查询使用此扩展汇率表而不是原始汇率表。

以下是我测试过的示例数据

create table exchange_rates
as
select 'GBP' FROM_CURRENCY,  'USD' TO_CURRENCY, 1.31  EXCHANGE_RATE from dual union all
select 'EUR' FROM_CURRENCY,  'USD' TO_CURRENCY, 1.16 EXCHANGE_RATE from dual union all
select 'AUD' FROM_CURRENCY,  'USD' TO_CURRENCY, .73 EXCHANGE_RATE from dual union all
select 'USD' FROM_CURRENCY,  'GBP' TO_CURRENCY, .76  EXCHANGE_RATE from dual union all
select 'USD' FROM_CURRENCY,  'EUR' TO_CURRENCY, .86 EXCHANGE_RATE from dual union all
select 'USD' FROM_CURRENCY,  'AUD' TO_CURRENCY, 1.36 EXCHANGE_RATE from dual union all
select 'GBP' FROM_CURRENCY,  'EUR' TO_CURRENCY, 1.12 EXCHANGE_RATE from dual;
© www.soinside.com 2019 - 2024. All rights reserved.