sql查询获取汇率

时间:2017-02-01 08:53:45

标签: sql oracle

鉴于以当地货币存储销售额的销售表和包含货币转换率的汇率表,为了获得每个销售日期的总销售额,我需要查询

销售表:

Sales Date  Sales Amount    Currency       
01-JAN-16            500    INR    
01-JAN-16            100    GBP    
02-JAN-16           1000    INR    
02-JAN-16            150    GBP    
03-JAN-16           1500    INR  

汇率表:

Source Currency  Target Currency  Exchange Rate  Effective Start Date
INR              USD                      0.014  31-DEC-15     
INR              USD                      0.015  02-JAN-16     
GBP              USD                       1.32  20-DEC-15     
GBP              USD                       1.30  01-JAN-16     
GBP              USD                       1.35  10-JAN-16   

不知道我该怎么做

我必须做两件与货币匹配的事情然后检查相同的日期汇率或者在sales_date之前

2 个答案:

答案 0 :(得分:0)

试试这个:

with SOURCE as
(
select s1.*, coalesce(e1.Rate, 1) as ExRate, row_number() over(partition by e2.Source order by e2.StartDate desc) as r_num
from Sales s1
left join Exchange e2
on s1.Currency = e2.Source
and e2.StartDate <= s1.SalesDate 
)
select SOURCE.*, SalesAmount*ExRate as USDAmount
from SOURCE 
where r_num = 1

答案 1 :(得分:0)

很久以前,Oracle为这种处理引入了分析函数 - 避免加入,这通常很昂贵(与查询中的其他内容相比,需要花费很长时间才能处理)。

在这类问题中,union all这两个表最有效,在需要时使用null列值;然后使用last_value函数,忽略空值,然后只收集结果。

<强>假设

  1. 汇率表具有各种目标货币的转换率,而不仅仅是美元。测试数据没有说明这一点,但在查询中我只选择target_currency = 'USD'允许的行。 (实际上,如果该表只有目标=美元的汇率,那么就不需要目标货币栏。)
  2. 汇率栏不可为空。 (它不应该!)
  3. 对于每个交易日期,对于相同的货币,汇率表中有一行具有相同或更早的有效开始日期。这是应在数据库级别维护的跨表约束。
  4. 查询(包括with子句中的测试数据 - 使用基表时不需要)

    with
         sales ( sales_date, sales_amount, currency ) as (       
           select to_date('01-JAN-16', 'dd-MON-rr'),  500, 'INR' from dual union all
           select to_date('01-JAN-16', 'dd-MON-rr'),  100, 'GBP' from dual union all
           select to_date('02-JAN-16', 'dd-MON-rr'), 1000, 'INR' from dual union all
           select to_date('02-JAN-16', 'dd-MON-rr'),  150, 'GBP' from dual union all
           select to_date('03-JAN-16', 'dd-MON-rr'), 1500, 'INR' from dual
         ),
         exch_rate ( source_currency, target_currency, exchange_rate, effective_date ) as (
           select 'INR', 'USD', 0.014, to_date('31-DEC-15', 'dd-MON-rr') from dual union all
           select 'INR', 'USD', 0.015, to_date('02-JAN-16', 'dd-MON-rr') from dual union all
           select 'GBP', 'USD',  1.32, to_date('20-DEC-15', 'dd-MON-rr') from dual union all
           select 'GBP', 'USD',  1.30, to_date('01-JAN-16', 'dd-MON-rr') from dual union all
           select 'GBP', 'USD',  1.35, to_date('10-JAN-16', 'dd-MON-rr') from dual
         ),
         prep ( dt, amt, src_curr, x_rate ) as (
           select  sales_date, sales_amount, currency, null from  sales
           union all
           select  effective_date, null, source_currency, exchange_rate 
             from  exch_rate
             where target_currency = 'USD'
         ),
         with_x_rates ( dt, amt, src_curr, x_rate ) as (
           select dt, amt, src_curr,
                  last_value (x_rate ignore nulls) 
                       over (partition by src_curr order by dt, x_rate) as x_rate
           from   prep
         )
    select   dt as sales_date, amt as sales_amount, src_curr as currency,
             x_rate as exchange_rate, 
             amt * x_rate as sales_amount_in_usd
    from     with_x_rates
    where    amt is not null
    order by sales_date, currency   --  if needed
    ;
    

    输出

    SALES_DATE SALES_AMOUNT CURRENCY EXCHANGE_RATE SALES_AMOUNT_IN_USD
    ---------- ------------ -------- ------------- -------------------
    01-JAN-16           100 GBP              1.300             130.000
    01-JAN-16           500 INR              0.014               7.000
    02-JAN-16           150 GBP              1.300             195.000
    02-JAN-16          1000 INR              0.015              15.000
    03-JAN-16          1500 INR              0.015              22.500
    
    5 rows selected.
    

    注意:查询输出的每个列都有正确的数据类型(日期,数字等)。格式化全部在SQL * Plus中完成;我们不想在SQL查询中格式化数据(将其转换为字符串),因为这可能不是最终产品;其输出可能会被进一步处理所消耗。

相关问题