我正在努力寻找更好的方法来实现这一目标:
给定一个样本表
DATE PRC_A PRC_B
05/17 10 10
06/17 X 10
07/17 10 X
08/17 10 X
09/17 X 20
目标: 如果有来自PRC_A
但不来自 的数据缺失PRC_B
,则计算该PRC_B's
日与PRC_B 前一天的价格差异。如果PRC_B's
还缺少前一天的价格,请继续返回日历,直到找到非空行。
例如:
06/17 缺失,prc_A
因此PRC_B's
价格之间的差异将是 0。在 09/17 上,差异将是10,因为下一个可用的数据是在 06/17 上。
现在我正在使用 LAG 函数来计算差异。但是,当前一行也为空时,我被卡住了。我已经设置了一个计数器,并考虑做一个 while 循环,但在循环之前应该有一个条件,但它不起作用。我是 sql 新手,不习惯语法和规则。到目前为止,这是我的代码。这是不正确的,但这是我的开始:
DECLARE
counter INT:=1
BEGIN
SELECT ....
case
when prc_A is null and prc_B is not null
then (prc_B- LAG( prc_B, 1,0) OVER ())
when prc_A is null andprc_B is not null and (LAG(prc_B, 1,0) OVER ()) is null then
case
when LAG( prc_B, 2,0) OVER () is null
then counter = counter +1 and
(prc_B - LAG( prc_B, counter,0) OVER ())
end
else
0
end as DIFF,
FROM ...
ORDER BY ..
END;
那么我怎样才能实现我的目标呢?
这一切都可以用普通的 SQL 简单有效地完成 - 不需要过程代码。
我不确定您想要什么输出格式,但您应该能够根据您的需要调整解决方案。
根据您的描述,您正在寻找LAST_VALUE()
功能,而不是LAG()
. LAST_VALUE()
允许您忽略空值。注意窗口子句 ( ROWS BETWEEN...
) - 默认是包含当前行,而您不希望这样,因此您必须有一个显式的窗口子句。
编辑:正如@boneist 在下面的评论中指出的那样,自 Oracle 11.2 以来,该函数LAG()
添加了该IGNORE NULLS
选项 - 它的优点是默认情况下它会“回溯”较早的行,从最近的行开始 - 所以窗口子句将不需要。在 Oracle 11.2 或更高版本LAST_VALUE()
中,可以使用LAG(prc_b ignore nulls) over (order by dt)
.
with
test_data ( dt, prc_a, prc_b ) as (
select date '2017-05-01', 10, 10 from dual union all
select date '2017-06-01', null, 10 from dual union all
select date '2017-07-01', 10, null from dual union all
select date '2017-08-01', 10, null from dual union all
select date '2017-09-01', null, 20 from dual
)
-- End of test data (not part of the solution). SQL query begins below this line.
select dt, prc_a, prc_b,
case when prc_a is null
then prc_b - last_value(prc_b ignore nulls) over (order by dt
rows between unbounded preceding and 1 preceding)
end as prc_b_diff
from test_data
;
DT PRC_A PRC_B PRC_B_DIFF
---------- ---------- ---------- ----------
2017-05-01 10 10
2017-06-01 10 0
2017-07-01 10
2017-08-01 10
2017-09-01 20 10
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句