Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL:Last_Value() gibt falsches Ergebnis zurück (aber First_Value() funktioniert gut)

Hier ist eine kurze Abfrage, um das Verhalten zu veranschaulichen:

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)

Die Ausgabe der obigen Abfrage kann hier eingesehen werden (SQLFiddle hier ). ):

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

Nur wenige Leute denken an die impliziten Frames, die auf Fensterfunktionen angewendet werden, die einen ORDER BY annehmen Klausel. In diesem Fall verwenden Fenster standardmäßig den Frame RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE ist nicht genau dasselbe wie ROWS, aber das ist eine andere Geschichte). Stellen Sie sich das so vor:

  • Auf der Zeile mit v = 1 der Rahmen des bestellten Fensters erstreckt sich über v IN (1)
  • Auf der Zeile mit v = 2 der Rahmen des geordneten Fensters erstreckt sich über v IN (1, 2)
  • Auf der Zeile mit v = 3 der Rahmen des geordneten Fensters erstreckt sich über v IN (1, 2, 3)
  • Auf der Zeile mit v = 4 der Rahmen des geordneten Fensters erstreckt sich über v IN (1, 2, 3, 4)

Wenn Sie dieses Verhalten verhindern möchten, haben Sie zwei Möglichkeiten:

  • Verwenden Sie einen expliziten ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING Klausel für bestellt Fensterfunktionen
  • Verwenden Sie kein ORDER BY -Klausel in jenen Fensterfunktionen, die es erlauben, sie wegzulassen (als MAX(v) OVER() )

Weitere Details werden in dieser Artikel über LEAD() , LAG() , FIRST_VALUE() und LAST_VALUE()