簡體   English   中英

sql查詢獲取匯率

[英]sql query to fetch exchange rate

給定一個以當地貨幣存儲銷售額的銷售表和一個包含貨幣兌換率的匯率表,以獲取每個銷售日期的美元總銷售額,我需要查詢

銷售表:

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 之前

嘗試這個:

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

很久以前,Oracle引入了用於這種處理的分析功能-避免通常很昂貴的聯接(與查詢中的其他所有事物相比,處理時間較長)。

在這種類型的問題中,最有效的方法是在需要的地方使用null列值來union all兩個表。 然后使用last_value函數,忽略空值,然后僅收集結果。

假設

  1. 匯率表具有多種目標貨幣的轉換率,而不僅僅是美元。 測試數據沒有說明這一點,但是在查詢中,我僅選擇了target_currency = 'USD'來允許這樣做。 (實際上,如果表中只有目標= USD的匯率,則不需要目標貨幣列)。
  2. 匯率欄不可為空。 (不應該!)
  3. 對於每個交易日期,對於相同的貨幣,匯率表中都有一行具有相同或更早的有效開始日期的行。 這是應該在數據庫級別上維護的跨表約束。

查詢 (包括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查詢中的數據(將其轉換為字符串),因為這可能不是最終產品; 其輸出可能會被進一步處理消耗。

這應該很容易理解

with ex as
(
select e.source_currency, e.exchange_rate, e.effective_start_date,
isnull(lead(dateadd(day, -1,cast(effective_start_date as date))) over(partition by source_currency order by effective_start_date ),cast('9999-12-31' as date)) eff_end_date
from exchange_rate e
) 
select s.sales_date, sum(round((s.sales_amount * e.exchange_rate),2)) amt
from ex e
 join sales_amount s
on e.source_currency = s.currency and
s.sales_date between e.effective_start_date and e.eff_end_date
group by s.sales_date
order by s.sales_date

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM