sql >> Databasteknik >  >> RDS >> Sqlserver

SQL:Last_Value() returnerar fel resultat (men First_Value() fungerar bra)

Här är en snabb fråga för att illustrera beteendet:

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)

Utdata från ovanstående fråga kan ses här (SQLFiddle här ):

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

Få människor tänker på de implicita ramarna som tillämpas på fönsterfunktioner som tar en ORDER BY klausul. I det här fallet används fönster som standard till ramen RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE är inte exakt detsamma som ROWS, men det är en annan historia). Tänk på det så här:

  • På raden med v = 1 det beställda fönstrets ram spänner över v IN (1)
  • På raden med v = 2 det beställda fönstrets ram spänner över v IN (1, 2)
  • På raden med v = 3 det beställda fönstrets ram spänner över v IN (1, 2, 3)
  • På raden med v = 4 det beställda fönstrets ram spänner över v IN (1, 2, 3, 4)

Om du vill förhindra det beteendet har du två alternativ:

  • Använd en uttrycklig ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING klausul för beställd fönsterfunktioner
  • Använd ingen ORDER BY sats i de fönsterfunktioner som gör det möjligt att utelämna dem (som MAX(v) OVER() )

Mer information förklaras i denna artikel om LEAD() , LAG() , FIRST_VALUE() och LAST_VALUE()



  1. Hur man returnerar tomma grupper i SQL GROUP BY-sats

  2. Hur man lagrar återkommande datum med tanke på sommartid

  3. Hämta det anslutna mysql-databasnamnet (JDBC)

  4. Uppdatera materialiserade vyer:Samtidighet, transaktionsbeteende