Неявное вычисление курсов валют в SQL из таблицы курсов валют - PullRequest
0 голосов
/ 02 июля 2018

У меня есть одна таблица данных с доходами в нескольких валютах (назовем ее 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 JPY в GBP:

  1. Найти курс JPY к USD - расчет = 1000 * EXCHANGE_RATE = 9
  2. Найти курс GBP к USD - расчет = 9 \ EXCHANGE_RATE = 7

В данный момент я сделал левое соединение для TRANSACTION_TABLE на EXCHANGE_RATE, но я потерян, куда идти дальше.

Любая помощь будет принята с благодарностью.

Запрос (очень простой), который я создал до сих пор, выглядит следующим образом, и я начинающий пользователь 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

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Я бы предложил сделать дополнительный шаг, чтобы развернуть вы обмениваетесь таблицей с обменными курсами, дополнительно определенными с использованием 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;
0 голосов
/ 02 июля 2018

Если ваша таблица 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'
...