SQL Practice Logo

SQLPractice Online

Window Frames (ROWS vs RANGE): Examples

Module: Window Functions

Basic ROWS vs RANGE Comparison with Ties

intermediate

Understanding how ROWS and RANGE handle duplicate ORDER BY values differently

-- Sample data with tied dates to demonstrate the difference

WITH daily_sales AS (

SELECT * FROM VALUES

('2024-01-01'::date, 'Product A', 100),

('2024-01-01'::date, 'Product B', 150), -- Same date (tie)

('2024-01-01'::date, 'Product C', 120), -- Same date (tie)

('2024-01-02'::date, 'Product A', 200),

('2024-01-03'::date, 'Product A', 180),

('2024-01-03'::date, 'Product B', 160) -- Same date (tie)

AS t(sale_date, product, amount)

)

SELECT

sale_date,

product,

amount,

-- ROWS: Counts exactly 2 physical rows (current + 1 preceding)

STRING_AGG(amount::text, ', ') OVER (

ORDER BY sale_date, product

ROWS BETWEEN 1 PRECEDING AND CURRENT ROW

) as rows_frame_values,

SUM(amount) OVER (

ORDER BY sale_date, product

ROWS BETWEEN 1 PRECEDING AND CURRENT ROW

) as rows_sum,

COUNT(*) OVER (

ORDER BY sale_date, product

ROWS BETWEEN 1 PRECEDING AND CURRENT ROW

) as rows_count,

-- RANGE: Includes all rows with same or preceding dates

STRING_AGG(amount::text, ', ') OVER (

ORDER BY sale_date

RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

) as range_frame_values,

SUM(amount) OVER (

ORDER BY sale_date

RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

) as range_sum,