XQuery 3.0 added windows over ordered sequences. A tumbling window cuts the sequence into non-overlapping pieces; a sliding window starts a new window at every item, so windows overlap. Each window has a start condition and an optional end condition, which can bind the current item, its position (at), and the previous and next items. only end drops a final window whose end condition never became true:
(: Daily totals with a tumbling window, a 3-order moving average with a sliding window :)
let $orders := doc("orders.xml")//order
return (
for tumbling window $w in $orders
start $s when true() end next $n when $n/@date ne $s/@date
return $s/@date || ": " || count($w) || " order(s), " || sum($w/@qty) || " units",
for sliding window $w in $orders
start at $i when true() only end at $j when $j - $i eq 2
return $w[1]/@id || "-" || $w[3]/@id || ": average quantity " || round(avg($w/@qty), 2)
)xquery window.xq"2026-09-28: 2 order(s), 3 units" "2026-09-29: 3 order(s), 6 units" "2026-09-30: 2 order(s), 3 units" "2026-10-01: 1 order(s), 1 units" "o1001-o1003: average quantity 2" "o1002-o1004: average quantity 1.67" "o1003-o1005: average quantity 2" "o1004-o1006: average quantity 1.67" "o1005-o1007: average quantity 1.67" "o1006-o1008: average quantity 1.33"
The tumbling window ends just before the next order has a new date, so each window is one day, the XML equivalent of a session or batch boundary in an event stream. The sliding window with only end yields exactly the six complete three-order windows, the same idea as a SQL window frame (Analytical SQL and Data Warehouses) or a Kafka Streams 129 hopping window (Apache Kafka and Managed Cloud Kafka).