sql 复制到月底的最新记录

sql to replicate the latest record through the end of the month

我需要根据每种货币的最新交易生成月底前的汇率。

例如,假设我们要处理 2 天的汇率(该文件可能包含 x 天的汇率),它们如下所示:

04/25/2015,GBP,USD,1.8
04/25/2015,USD,GBP,1.25
04/26/2015,GBP,USD,1.7346
04/26/2015,USD,GBP,1.1357

在此示例中,我需要在 4/26 获取两条记录并生成到月底的记录,因此输出需要如下所示:

04/27/2015,GBP,USD,1.7346
04/28/2015,GBP,USD,1.7346
04/29/2015,GBP,USD,1.7346
04/30/2015,GBP,USD,1.7346
04/27/2015,USD,GBP,1.1357
04/28/2015,USD,GBP,1.1357
04/29/2015,USD,GBP,1.1357
04/30/2015,USD,GBP,1.1357

我所做的是 PLSQL 中的以下程序,但这似乎并没有像我预期的那样工作。

DECLARE 
 l_max_date date;

 CURSOR C1 IS
 SELECT         FROM_CURRENCY_DATE,
                FROM_CURRENCY,
                TO_CURRENCY, 
                NUMERATOR_BUY,
                CONVERSION_RATE,
                LEAD(conversion_rate) OVER (PARTITION BY from_currency ORDER BY from_currency_date) AS LEAD_conversion_rate,                
                ROW_NUMBER() OVER (PARTITION BY from_currency ORDER BY from_currency_date DESC) AS rn
        FROM    exchange_rate_staging_tbl
        WHERE   valid_flag is null or valid_flag <> 'E';

cur_rec c1%rowtype;

BEGIN 

 SELECT MAX(from_currency_date)
 INTO l_max_date
 FROM exchange_rate_staging_tbl;


 FOR cur_rec IN c1 LOOP

   if cur_rec.lead_conversion_rate is null then -->Null means it is the latest transaction
   dbms_output.put_line(cur_rec.from_currency||' '||
                       cur_rec.to_currency||' '||
                       'Inside IF'||' '||
                       cur_rec.conversion_rate);
   ELSE --> Records here are not the latest transaction but they still need to be inserted with their respective exch rate
   --dbms_output.put_line(l_max_date||last_day(l_max_date)); 
   dbms_output.put_line(cur_rec.from_currency||' '||
                       cur_rec.to_currency||' '||
                       'Inside Else'||' '||
                       cur_rec.conversion_rate);
   END IF;

  l_max_date := l_max_date+1; 
  END LOOP; 
 END; 

以上程序输出:

GBP USD 25-APR-15 25-APR-15 Inside Else 1.8

GBP USD 26-APR-15 26-APR-15 Inside IF 1.7346

如何根据 SQL 或 PLSQL.

月底每种货币的最新交易生成记录

这个查询看起来很有希望:

with 
  dm as (select max(from_currency_date) d from exchange_rate_staging_tbl),
  dr as (select distinct from_currency fc, to_currency tc,
      last_value(conversion_rate ignore nulls) over 
        (partition by from_currency, to_currency order by from_currency_date 
        rows between unbounded preceding and unbounded following) rate
    from exchange_rate_staging_tbl, dm where from_currency_date = dm.d),
  days as (select d+level-1 day from dm connect by d+level-1 <= last_day(d))
select days.day, dr.fc, dr.tc, rate
  from days cross join dr 

SQLFiddle demo

有一个问题 - 如果 4 月 26 日我们有 GBP/USD 的汇率,但 USD/GBP 缺失,则只会复制 GBP/USD。 我不知道这种情况是否会发生,如果是,则必须更改查询。也有比较多的疑问比如 如果相同货币等有两种汇率怎么办,但我不知道在这种情况下你想要什么。

它是如何工作的:

  • 第一个子查询 dm 只查找 table 中的最大日期,您可能需要在此处添加月份过滤器,例如 where from_currency_date <= 'date 2015-04-30'
  • dr收集从这一天开始所有货币汇率的信息,distinct last_value保证每对货币只取一行,
  • days 是分层日期生成器,生成到月底的缺失日期,
  • 最终 select 加入日期和费率。

根据评论编辑:

How can I still bring the converstion rate for 4/25

with 
  dm as (select date '2015-04-25' d from dual), 
  dc as (
    select distinct from_currency, to_currency
      from exchange_rate_staging_tbl, dm 
      where from_currency_date between d and last_day(d)),
  days as (
    select d+level-1 from_currency_date 
      from dm connect by d+level-1 <= last_day(d))
select from_currency_date, from_currency, to_currency,
    last_value(conversion_rate ignore nulls) over 
      (partition by from_currency, to_currency order by from_currency_date 
      rows unbounded preceding ) rate 
  from dc cross join days 
  left join exchange_rate_staging_tbl e
    using (from_currency_date, from_currency, to_currency)  
  order by from_currency_date, from_currency, to_currency

SQLFiddle demo

此查询显示从给定日期(您在第一行定义它)到月末填补空白的数据 - 假设我们没有周六和周日的转化率,查询会用周五的数据填补这一空白。


函数last_value() 查找转换率的最后一个值 来自某些以某种方式分组(分区)的值。在我们的例子中,这些分区是货币对,顺序是 currency_date。 用人的话来说:找到给定时期内每对货币的兑换率的最后一个非空值。请注意,每一行的这段时间都会发生变化。 Last_value 是使用范围非常广泛的分析函数之一。 关于这些函数的好文章:Analytic functions by Example.

您的数据看起来不像我见过的任何费率数据。通常,一切都以一种货币为参考。就我而言,它是美元。现在您每天只需为每种货币输入一次。像这样:

Effective  Code Factor
2015-05-02 GBP  0.662251656 --based on today's rate of 1.51 GBP->USD

从美元兑换英镑:美元 * 系数 = 英镑
从 GBP 到 USD: GBP / factor = USD

有一个幻灯片演示文稿显示了这样一个 table 设计 here。货币讨论从slide/page12开始,查询在第16页。table设计简单:

create table XRates(
    Code       char( 3 ) not null,
    Effective  date not null,
    Factor     decimal( 12, 9 ) not null
    constraint PK_XRates primary key( Code, Effective )
);

有关该设计的几个不错的功能是您可以将历史汇率保持在相同 table 并且不需要每天输入。仅当汇率发生变化时才进行分录。查询 returns 在给定日期生效的汇率,即使该汇率是由一周前的条目建立的(在今天的货币市场中不太可能)。