sql >> Base de Datos >  >> RDS >> Sqlserver

SQL:Last_Value() devuelve un resultado incorrecto (pero First_Value() funciona bien)

Aquí hay una consulta rápida para ilustrar el comportamiento:

select 
  v,

  -- FIRST_VALUE() and LAST_VALUE()
  first_value(v) over(order by v) f1,
  first_value(v) over(order by v rows between unbounded preceding and current row) f2,
  first_value(v) over(order by v rows between unbounded preceding and unbounded following) f3,
  last_value (v) over(order by v) l1,
  last_value (v) over(order by v rows between unbounded preceding and current row) l2,
  last_value (v) over(order by v rows between unbounded preceding and unbounded following) l3,

  -- For completeness' sake, let's also compare the above with MAX()
  max        (v) over() m1,
  max        (v) over(order by v) m2,
  max        (v) over(order by v rows between unbounded preceding and current row) m3,
  max        (v) over(order by v rows between unbounded preceding and unbounded following) m4
from (values(1),(2),(3),(4)) t(v)

El resultado de la consulta anterior se puede ver aquí (SQLFiddle aquí ):

| V | F1 | F2 | F3 | L1 | L2 | L3 | M1 | M2 | M3 | M4 |
|---|----|----|----|----|----|----|----|----|----|----|
| 1 |  1 |  1 |  1 |  1 |  1 |  4 |  4 |  1 |  1 |  4 |
| 2 |  1 |  1 |  1 |  2 |  2 |  4 |  4 |  2 |  2 |  4 |
| 3 |  1 |  1 |  1 |  3 |  3 |  4 |  4 |  3 |  3 |  4 |
| 4 |  1 |  1 |  1 |  4 |  4 |  4 |  4 |  4 |  4 |  4 |

Pocas personas piensan en los marcos implícitos que se aplican a las funciones de ventana que toman un ORDER BY cláusula. En este caso, las ventanas tienen por defecto el marco RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGO no es exactamente lo mismo que FILAS, pero esa es otra historia). Piénsalo de esta manera:

  • En la fila con v = 1 el marco de la ventana ordenada abarca v IN (1)
  • En la fila con v = 2 el marco de la ventana ordenada abarca v IN (1, 2)
  • En la fila con v = 3 el marco de la ventana ordenada abarca v IN (1, 2, 3)
  • En la fila con v = 4 el marco de la ventana ordenada abarca v IN (1, 2, 3, 4)

Si quieres evitar ese comportamiento, tienes dos opciones:

  • Use un ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING cláusula para pedido funciones de ventana
  • No usar ORDER BY cláusula en aquellas funciones de ventana que permiten omitirlas (como MAX(v) OVER() )

Se explican más detalles en este artículo sobre LEAD() , LAG() , FIRST_VALUE() y LAST_VALUE()