sql >> Database >  >> RDS >> Sqlserver

SQL:Last_Value() geeft een verkeerd resultaat terug (maar First_Value() werkt prima)

Hier is een korte vraag om het gedrag te illustreren:

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)

De uitvoer van de bovenstaande query kan hier worden bekeken (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 |

Weinig mensen denken aan de impliciete frames die worden toegepast op vensterfuncties die een ORDER BY hebben clausule. In dit geval worden vensters standaard ingesteld op het frame RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE is niet precies hetzelfde als RIJEN, maar dat is een ander verhaal). Denk er zo over na:

  • Op de rij met v = 1 het bestelde raamkozijn omspant v IN (1)
  • Op de rij met v = 2 het bestelde raamkozijn omspant v IN (1, 2)
  • Op de rij met v = 3 het bestelde raamkozijn omspant v IN (1, 2, 3)
  • Op de rij met v = 4 het bestelde raamkozijn omspant v IN (1, 2, 3, 4)

Als je dat gedrag wilt voorkomen, heb je twee opties:

  • Gebruik een expliciete ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING clausule voor besteld vensterfuncties
  • Gebruik geen ORDER BY clausule in die vensterfuncties die het mogelijk maken om ze weg te laten (als MAX(v) OVER() )

Meer details worden uitgelegd in dit artikel over LEAD() , LAG() , FIRST_VALUE() en LAST_VALUE()



  1. Hoe mysql opgeslagen procedure te verbergen

  2. Waarschuwing:mysql_real_escape_string() [function.mysql-real-escape-string]:er kon geen link naar de server tot stand worden gebracht in

  3. Oracle:als tabel bestaat

  4. Testen van PostgreSQL-functies die refcursor verbruiken en retourneren