Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

SQL :Last_Value() renvoie un résultat erroné (mais First_Value() fonctionne correctement)

Voici une requête rapide pour illustrer le comportement :

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)

La sortie de la requête ci-dessus peut être vue ici (SQLFiddle ici ):

| 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 |

Peu de gens pensent aux cadres implicites appliqués aux fonctions de fenêtre qui prennent un ORDER BY clause. Dans ce cas, les fenêtres utilisent par défaut le cadre RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE n'est pas exactement la même chose que ROWS, mais c'est une autre histoire). Pensez-y de cette façon :

  • Sur la ligne avec v = 1 le cadre de la fenêtre ordonnée s'étend sur v IN (1)
  • Sur la ligne avec v = 2 le cadre de la fenêtre ordonnée s'étend sur v IN (1, 2)
  • Sur la ligne avec v = 3 le cadre de la fenêtre ordonnée s'étend sur v IN (1, 2, 3)
  • Sur la ligne avec v = 4 le cadre de la fenêtre ordonnée s'étend sur v IN (1, 2, 3, 4)

Si vous souhaitez empêcher ce comportement, vous avez deux options :

  • Utilisez un ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING clause pour commandé fonctions de fenêtre
  • N'utilisez pas de ORDER BY clause dans ces fonctions de fenêtre qui permettent de les omettre (comme MAX(v) OVER() )

Plus de détails sont expliqués dans cet article sur LEAD() , LAG() , FIRST_VALUE() et LAST_VALUE()