Ao testar minha resposta para SQL - obtendo dados da primeira e última linha de cada grupo , notei algo estranho. As funções first_value
e last_value
janela parecem se comportar de forma diferente.
Como esperado, first_value(col1) over (order by col2)
localiza o valor de col1
na linha com o valor mínimo para col2
. Mas last_value(col1) over (order by col2)
parece encontrar o valor para a linha atual. last_value
parece não estar relacionado ao grupo ou partição em que está operando.
Para a consulta abaixo:
id Session ID bal
0 00000002 100
1 00000002 120
2 00000002 140
3 00000001 900
4 00000001 800
5 00000001 500
A expressão:
last_value(bal) over (partition by [Session ID] order by id) as lv
Retorna algo diferente de:
first_value(bal) over (partition by [Session ID] order by id DESC) as fv_desc
Aqui está o resultado (observe que o valor das lv
alterações dentro de um grupo):
lv fv_desc
500 500
800 500
900 500
140 140
120 140
100 140
Exemplo no SQL Fiddle com algumas colunas extras. Inverter order by
ou omitir partition by
não parece afetar o que last_value()
retorna.
Se eu li a página do MSDN corretamente, sugere que last_value()
deve funcionar como o oposto de first_value()
, o que é diferente do que observei durante o teste.
Faz last_value()
o que é suposto fazer? Por que last_value()
permite que você especifique uma cláusula partition
and/or order by
quando parece não usar nenhum dos dois?
Isso acontece porque o quadro de janela padrão é
range between unbounded preceding and current row
, portanto,last_value()
nunca olha além da linha atual, a menos que você altere o quadro.Do MSDN:
Como
last_value()
possui uma cláusula opcionalorder by
, sua moldura de janela padrão termina na linha atual. Portanto, com o quadro padrão, não importa qual partição ou ordem você escolha,last_value()
retorna o valor da linha atual.