表左连接自身返回NULL

时间:2015-02-20 15:46:39

标签: sql oracle oracle11g

我有一张像

这样的表格
Tdate          Symbol       new_close
20100110        xxx           1.2
20100111        xxx           1.3
...
20100110        yyy           1.1
20100111        yyy           1.5

其中Tdate存储为整数,并且每个符号每天更新一次。我想通过将new_close值减去前一个值来生成一个新表,它看起来像这个

    Tdate          Symbol       delta
    20100110        xxx           =1.2-1.2
    20100111        xxx           =1.3-1.2
    ...
    20100110        yyy           =1.1-1.1
    20100111        yyy           =1.5-1.1

这是我的代码

with delta as
( select a.Tdate as TDate,  a.Symbol as Symbol,
a.new_close-b.new_close as Pdelta, b.new_close as oldPrice
   from ctsWithSplit a left join ctsWithSplit b
   on a.TDate-b.TDate=1 and a.Symbol=b.Symbol)

但是,在新生成的表中,某些delta值为NULL,请问如何解决?

2 个答案:

答案 0 :(得分:1)

为什么TDATE被存储为数字?如果日期是该月的第一天,您的查询将无法找到前一天 - 例如:20150201 - 20150131 = 70,而在1月31日至2月1日期间只有一天。

将日期存储为DATETIMESTAMP数据类型,然后您可以让Oracle有机会更正日期算法。

也许你会在以下的事情之后:

with sample_data as (select to_date('10/01/2010', 'dd/mm/yyyy hh24:mi:ss') tdate, 'xxx' symbol, 1.2 new_close from dual union all
                     select to_date('11/01/2010', 'dd/mm/yyyy hh24:mi:ss') tdate, 'xxx' symbol, 1.3 new_close from dual union all
                     select to_date('10/01/2010', 'dd/mm/yyyy hh24:mi:ss') tdate, 'yyy' symbol, 1.1 new_close from dual union all
                     select to_date('11/01/2010', 'dd/mm/yyyy hh24:mi:ss') tdate, 'yyy' symbol, 1.5 new_close from dual)
select tdate,
       symbol,
       new_close - lag(new_close, 1, new_close) over (partition by symbol order by tdate) delta
from   sample_data;

TDATE      SYMBOL DELTA
---------- ------ -----
10/01/2010 xxx      0.0
11/01/2010 xxx      0.1
10/01/2010 yyy      0.0
11/01/2010 yyy      0.4

如果您从未使用过分析功能,那么我建议您查阅它们 - 它们非常有用且非常强大。

N.B。如果您无法将TDATE列转换为DATE数据类型,则需要使用to_date()将列转换为您运行的任何查询中的日期。

答案 1 :(得分:0)

当您的左连接在b中找不到匹配的行时(即在第一个Tdate上找到匹配的行,或者前一天没有Tdate的行) b.new_close将为NULL,减法的结果也将为NULL。 尝试:

select
    a.Tdate as TDate,
    a.Symbol as Symbol,
    CASE WHEN b.new_close IS NULL THEN 0 ELSE a.new_close-b.new_close END as Pdelta,
    b.new_close as oldPrice
from ctsWithSplit a
left join ctsWithSplit b
    on a.TDate-b.TDate=1
    and a.Symbol=b.Symbol