2016-11-17 88 views
2

我在IGNORE NULLS参数中看到了Vertica的FIRST_VALUE()分析函数中的意外行为。它不应该返回NULL。IGNORE NULLS(Vertica)在FIRST_VALUE()中出现意外的行为

问题就在这个小桌子出现:

drop table if exists temp; 
create table temp (time_ timestamp(6), name varchar(10)); 
insert into temp (time_) values ('2016-03-18 20:32:16.144'); 
insert into temp (time_, name) values ('2016-03-18 20:52:09.062', 'abc'); 

下面是表的内容(从临时选择*):

time_     | name 
------------------------+-------- 
2016-03-18 20:32:16.144 | <null> 
2016-03-18 20:52:09.062 | abc 

这里是我运行查询:

select time_, 
    first_value(name ignore nulls) over (order by time_) first_name 
from temp; 

下面是该查询返回的结果:

time_     | first_name 
------------------------+------------ 
2016-03-18 20:32:16.144 | <null> 
2016-03-18 20:52:09.062 | abc 

下面是这个查询我希望(与欲望)的结果:

time_     | first_name 
------------------------+------------ 
2016-03-18 20:32:16.144 | abc 
2016-03-18 20:52:09.062 | abc 

难道上面的查询有一个很基本的语法错误? Vertica Community Edition 7.1.1上会出现此问题。

回答

1

功能按预期工作。
over (order by time_)over (order by time_ range unbounded preceding)的快捷方式,它是over (order by time_ range between unbounded preceding and current row)的快捷方式,这意味着每行只能看到其前面的行,包括其自身。
第一行只能看到它自己,因此它的范围内没有非NULL值。

如果你想整个范围内的第一个非NULL值,你必须指定全范围:

first_value(name ignore nulls) over 
    (order by time_ range between unbounded preceding and unbounded following) first_name 

不,这是definitly不是一个错误。

您可能一直在使用像sum(x) over (order by y)这样的语法来运行总计,而RANGE UNBOUNDED PRECEDING的默认窗口对您来说似乎很自然。
由于您尚未为FIRST_VALUE函数定义显式窗口,因此您一直使用相同的默认窗口。

这里是另一个测试案例:

ts val 
-- ---- 
1 NULL 
2 X 
3 NULL 
4 Y 
5 NULL 

你会期望从下面的函数来获得?

last_value (val) order (by ts) 

您希望从以下函数中获得什么?

last_value (val ignore nulls) order (by ts) 
+0

非常有趣。看起来更像是一个错误,而不是一个功能,但很高兴知道整个故事。谢谢! – verbatross

+0

@verbatross,看我编辑的答案。 –

+0

感谢您的额外示例!超级有用。 – verbatross

2

这就是我的想法把我

select time_ 
     ,first_value(name) over (order by case when name is null then 1 else 0 end,time_) FirstName 
from temp A 
order by time_ 

返回

time_    FirstName 
20:32:16.1440000 abc 
20:52:09.0620000 abc 
+0

感谢您的解决方法。 (在Vertica CE 7.1中。1这个确切的语法不起作用,但你可以这样做:'选择time_,first_value(name)over(按大小写命名,当name为null,然后1 else 0 end,time_)first_name from temp')。但IGNORE NULLS不应该做这件事吗? – verbatross

+0

@verbatross快乐,你可以调整。令人震惊的是,它不支持IIF() –

+0

@verbatross搜索...但到目前为止,我只看到AWS –