【问题标题】:Implicitly Calculate Exchange Rates in SQL from Exchange Rate table从汇率表隐式计算 SQL 中的汇率
【发布时间】:2018-12-10 17:07:50
【问题描述】:

我有一张包含多种货币收入的数据表(我们称之为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. 查找日元兑美元汇率 - 计算 = 1000 * EXCHANGE_RATE = 9
  2. 查找英镑兑美元汇率 - 计算 = 9 \ EXCHANGE_RATE = 7

目前,我在EXCHANGE_RATE 上为TRANSACTION_TABLE 完成了左连接,但我不知道下一步该去哪里。

任何帮助将不胜感激。

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

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


    【解决方案1】:

    如果您的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作为转账货币另外定义的汇率。

      此查询添加以美元计算的新费率。这是一个简单的内连接约束,因此计算是通过“美元”进行的,并且从货币和到货币是不同的。 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;
      

      【讨论】:

        猜你喜欢
        • 2018-03-18
        • 1970-01-01
        • 1970-01-01
        • 2020-10-01
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 2017-06-12
        • 1970-01-01
        相关资源
        最近更新 更多