Sql 什么';第一个值查询有什么问题?
查询如下:Sql 什么';第一个值查询有什么问题?,sql,oracle,Sql,Oracle,查询如下: with t as ( select 450 id, null txt , 3488 id_usr from dual union all select 449 , null , 3488 from dual union all select 79 , 'A' , 3488 from dual union all select 78 , 'X' , 3488 from dual )
with t
as (
select 450 id, null txt , 3488 id_usr from dual union all
select 449 , null , 3488 from dual union all
select 79 , 'A' , 3488 from dual union all
select 78 , 'X' , 3488 from dual
)
select id
, txt
, id_usr
, first_value(txt ignore nulls) over (partition by id_usr order by id desc) first_one
from t
并返回:
ID TXT D_USR FIRST_ONE
450 3488
449 3488
79 A 3488 A
78 X 3488 A
这是预期的结果:
ID TXT ID_USR FIRST_ONE
450 3488 A
449 3488 A
79 A 3488 A
78 X 3488 A
有什么问题以及原因?对于
第一个值
(与任何其他分析函数一样)的默认范围/行
在无界的前一行和当前行之间
如果添加IGNORE NULLS
,则在构建范围时不考虑NULL
值
范围
变为除空行(它不是有效的OVER
子句)之外的无界前一行和当前行之间的
由于txt
中的NULL
具有较高的id
,因此首先选择它们,并且它们的范围为空,因为它们之间没有非NULL
行,并且前面没有无界的
您应该更改查询的orderby
或RANGE
子句
通过
更改顺序会将id为NULL
的行置于窗口的末尾,以便始终首先选择非NULL
值(如果有),并且范围将保证从该值开始:
with t
as (
select 450 id, null txt , 3488 id_usr from dual union all
select 449 , null , 3488 from dual union all
select 79 , 'A' , 3488 from dual union all
select 78 , 'X' , 3488 from dual
)
select id
, txt
, id_usr
, first_value(txt) over (partition by id_usr order by NVL2(TXT, NULL, id) DESC) first_one
from t
更改RANGE
会重新定义RANGE,以包括分区中的所有非NULL
行:
with t
as (
select 450 id, null txt , 3488 id_usr from dual union all
select 449 , null , 3488 from dual union all
select 79 , 'A' , 3488 from dual union all
select 78 , 'X' , 3488 from dual
)
select id
, txt
, id_usr
, first_value(txt IGNORE NULLS) over (partition by id_usr order by id DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) first_one
from t
你的意思是“ignorenulls”子句不是用于确定“first_值”,而是用于窗口处理吗?@FerranB:不完全是。它从按id
排序的范围中选择第一个非NULL
值。如果在您的示例中,将450
替换为1
,它将为其选择“A”。我最好重写它,它现在很混乱。@Dave:它们都很重要。它将选择NULL
作为FIRST_值
,如果不是为IGNORE NULLS
“当您指定IGNORE NULLS时,函数会忽略NULLS。”是的,但只确定第一个_值,而不是窗口。这对这个问题毫无意义。问题是,正如您所说,窗口是从当前行开始的,而不是从所有分区行开始的。