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

SQL:Last_Value() returnerer forkert resultat (men First_Value() fungerer fint)

Her er en hurtig forespørgsel til at illustrere adfærden:

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)

Outputtet af ovenstående forespørgsel kan ses her (SQLFiddle her ):

| 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å mennesker tænker på de implicitte rammer, der anvendes på vinduesfunktioner, der tager en ORDER BY klausul. I dette tilfælde er vinduer standard til rammen RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE er ikke helt det samme som ROWS, men det er en anden historie). Tænk over det på denne måde:

  • På rækken med v = 1 det bestilte vindues ramme spænder over v IN (1)
  • På rækken med v = 2 det bestilte vindues ramme spænder over v IN (1, 2)
  • På rækken med v = 3 det bestilte vindues ramme spænder over v IN (1, 2, 3)
  • På rækken med v = 4 det bestilte vindues ramme spænder over v IN (1, 2, 3, 4)

Hvis du vil forhindre den adfærd, har du to muligheder:

  • Brug en eksplicit ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING klausul for beordret vinduesfunktioner
  • Brug ingen ORDER BY klausul i de vinduesfunktioner, der gør det muligt at udelade dem (som MAX(v) OVER() )

Flere detaljer er forklaret i denne artikel om LEAD() , LAG() , FIRST_VALUE() og LAST_VALUE()



  1. Google Cloud SQL med SSL fra Compute Engine og/eller eksternt netværk

  2. MySQL kontroller, om tabellen allerede eksisterer

  3. Gruppering af sæt:Vis subtotaler i en anden specifik kolonne?

  4. Sammenføjning af forskellige tabeller baseret på kolonneværdi