Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

SQL:Last_Value() restituisce un risultato errato (ma First_Value() funziona bene)

Ecco una rapida query per illustrare il comportamento:

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)

L'output della query precedente può essere visualizzato qui (SQLFiddle qui ):

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

Poche persone pensano ai frame impliciti applicati alle funzioni della finestra che accettano un ORDER BY clausola. In questo caso, le finestre sono di default sulla cornice RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE non è esattamente lo stesso di ROWS, ma questa è un'altra storia). Pensaci in questo modo:

  • Sulla riga con v = 1 la cornice della finestra ordinata si estende su v IN (1)
  • Sulla riga con v = 2 la cornice della finestra ordinata si estende su v IN (1, 2)
  • Sulla riga con v = 3 la cornice della finestra ordinata si estende su v IN (1, 2, 3)
  • Sulla riga con v = 4 la cornice della finestra ordinata si estende su v IN (1, 2, 3, 4)

Se vuoi prevenire questo comportamento, hai due opzioni:

  • Utilizza un esplicito ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING clausola per ordinato funzioni della finestra
  • Non utilizzare ORDER BY clausola in quelle funzioni della finestra che consentono di ometterle (come MAX(v) OVER() )

Maggiori dettagli sono spiegati in questo articolo su LEAD() , LAG() , FIRST_VALUE() e LAST_VALUE()