sql复制到月底的最新记录
Posted
技术标签:
【中文标题】sql复制到月底的最新记录【英文标题】:sql to replicate the latest record through the end of the month 【发布时间】:2015-05-01 17:55:38 【问题描述】:我需要根据每种货币的最新交易生成截至月底的汇率。
例如,假设我们需要处理 2 天的汇率(该文件可能会带来 x 天的汇率),它们如下所示:
2015 年 4 月 25 日,英镑,美元,1.8 2015 年 4 月 25 日,美元,英镑,1.25 2015 年 4 月 26 日,英镑,美元,1.7346 2015 年 4 月 26 日,美元,英镑,1.1357在此示例中,我需要在 4/26 获取两条记录并生成到月底的记录,因此输出需要如下所示:
2015 年 4 月 27 日,英镑,美元,1.7346 2015 年 4 月 28 日,英镑,美元,1.7346 2015 年 4 月 29 日,英镑,美元,1.7346 2015 年 4 月 30 日,英镑,美元,1.7346 2015 年 4 月 27 日,美元,英镑,1.1357 2015 年 4 月 28 日,美元,英镑,1.1357 2015 年 4 月 29 日,美元,英镑,1.1357 2015 年 4 月 30 日,美元,英镑,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 内部 IF 1.7346
我将如何在 SQL 或 PLSQL 中根据每个货币的最新交易生成记录。
【问题讨论】:
获取缺失日期列表(例如通过递归查询),选择最大日期和值或这个日期,加入并插入 我用我所有的研究和代码编辑了这篇文章。您能详细说明一下您的 cmets 吗? 【参考方案1】:这个查询看起来很有希望:
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
只是在表中查找最大日期,您可能想在此处添加月份过滤器,例如where from_currency_date <= 'date 2015-04-30'
,
dr
收集当天所有货币汇率的信息,distinct last_value
保证每对货币只占用一行,
days
是分层日期生成器,生成到月底的缺失日期,
最终选择加入日期和费率。
根据评论编辑:
我怎样才能仍然带来 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() 查找转化率的最后一个值
从某种以某种方式分组(分区)的值集。在我们的例子中,这些分区是货币对,order 是 currency_date。
用人类的话来说:找到给定时期内每对货币的兑换率的最后一个非空值。请注意,此期间每行都会发生变化。 Last_value
是使用范围非常广泛的分析函数之一。
关于这些功能的好文章:Analytic functions by Example。
【讨论】:
我运行了您的查询,我认为它有效,但我注意到它缺少 4/25 的信息。它带来 4/26 并持续到月底(这也是我所需要的)。除此之外,还需要反映 4/25。我怎样才能仍然带来 4/25 的转化率? 我已经编辑了答案,请看底部。还更正了第一部分中指向 SQLFiddle 的链接。 非常感谢@Ponder Stibbons,您的最后一个查询似乎按预期工作。此外,您发送的链接非常有帮助。您能否详细说明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
在查询中的作用?
乐于助人。我为last_value
添加了解释,请参阅答案中的最后编辑。很抱歉有任何语言错误,英语不是我的主要语言。【参考方案2】:
您的数据看起来不像我见过的任何费率数据。通常,一切都以一种货币为参考。就我而言,它是美元。现在,您每天只需为每种货币输入一个条目。像这样:
Effective Code Factor
2015-05-02 GBP 0.662251656 --based on today's rate of 1.51 GBP->USD
从美元到英镑:美元 * 因子 = 英镑 从英镑到美元:英镑/因子=美元
有一个幻灯片演示显示了这样的表格设计here。货币讨论从幻灯片/第 12 页开始,查询从第 16 页开始。表格设计很简单:
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 )
);
该设计的几个不错的功能是您可以在同一张表中维护历史汇率,并且不需要每日输入。仅当汇率发生变化时才进行输入。该查询返回在给定日期生效的汇率,即使该汇率是由一周前的条目确定的(在今天的货币市场中不太可能)。
【讨论】:
以上是关于sql复制到月底的最新记录的主要内容,如果未能解决你的问题,请参考以下文章
SQL 如何复制一条记录的指定字段的内容到另一条记录的指定字段?
如何在 mysql 5.7 上显示从月份的第一个日期到 MYSQL 5.7 上的月底日期的日期? [复制]