WINDOW FUNCTIONS (FIRST_VALUE / LAST_VALUE / NTH_VALUE)
Feb 23, 2026
·
5
min read
Category: Window/Analytic Functions
Platform Support:
✅ Snowflake | ✅ BigQuery | ✅ Databricks
Description
Access values from specific positions within a window frame. FIRST_VALUE returns the first value, LAST_VALUE returns the last value, and NTH_VALUE returns the value at a specific position. Essential for comparing values across rows in an ordered set.
Syntax
Window Frame:
Platform-Specific Notes
All Platforms:
Standard SQL window functions
Identical syntax and behavior
Default frame: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
LAST_VALUE requires explicit frame to get actual last value
Example 1: FIRST_VALUE - Compare with First in Group
All Platforms:
Sample Data (products table):
product_id | product_category | product_name | price |
|---|---|---|---|
1 | Electronics | Mouse | 25.00 |
2 | Electronics | Keyboard | 89.99 |
3 | Electronics | Monitor | 299.99 |
4 | Furniture | Chair | 149.99 |
5 | Furniture | Desk | 399.99 |
6 | Furniture | Shelf | 79.99 |
Result:
product_category | product_name | price | cheapest_product | cheapest_price | price_premium |
|---|---|---|---|---|---|
Electronics | Mouse | 25.00 | Mouse | 25.00 | 0.00 |
Electronics | Keyboard | 89.99 | Mouse | 25.00 | 64.99 |
Electronics | Monitor | 299.99 | Mouse | 25.00 | 274.99 |
Furniture | Shelf | 79.99 | Shelf | 79.99 | 0.00 |
Furniture | Chair | 149.99 | Shelf | 79.99 | 70.00 |
Furniture | Desk | 399.99 | Shelf | 79.99 | 320.00 |
Example 2: LAST_VALUE with Proper Frame
All Platforms:
Sample Data (daily_sales table):
sale_date | product_name | daily_sales |
|---|---|---|
2024-01-15 | Laptop | 1000 |
2024-01-16 | Laptop | 1200 |
2024-01-17 | Laptop | 1100 |
2024-01-18 | Laptop | 1300 |
2024-01-19 | Laptop | 900 |
Result:
sale_date | product_name | daily_sales | incorrect_last_value | correct_last_value | week_final_sales |
|---|---|---|---|---|---|
2024-01-15 | Laptop | 1000 | 1000 | 900 | 1100 |
2024-01-16 | Laptop | 1200 | 1200 | 900 | 1100 |
2024-01-17 | Laptop | 1100 | 1100 | 900 | 1100 |
2024-01-18 | Laptop | 1300 | 1300 | 900 | 900 |
2024-01-19 | Laptop | 900 | 900 | 900 | 900 |
Example 3: NTH_VALUE - Access Specific Positions
All Platforms:
Sample Data (employees table):
employee_id | employee_name | department | salary |
|---|---|---|---|
1 | Alice | Sales | 95000 |
2 | Bob | Sales | 75000 |
3 | Carol | Sales | 85000 |
4 | David | Sales | 70000 |
5 | Emma | IT | 110000 |
6 | Frank | IT | 95000 |
7 | Grace | IT | 100000 |
Result:
employee_id | employee_name | salary | department | highest_salary | second_highest | third_highest | median_salary |
|---|---|---|---|---|---|---|---|
1 | Alice | 95000 | Sales | 95000 | 85000 | 75000 | 80000 |
3 | Carol | 85000 | Sales | 95000 | 85000 | 75000 | 80000 |
2 | Bob | 75000 | Sales | 95000 | 85000 | 75000 | 80000 |
4 | David | 70000 | Sales | 95000 | 85000 | 75000 | 80000 |
5 | Emma | 110000 | IT | 110000 | 100000 | 95000 | 100000 |
7 | Grace | 100000 | IT | 110000 | 100000 | 95000 | 100000 |
6 | Frank | 95000 | IT | 110000 | 100000 | 95000 | 100000 |
Example 4: Stock Price Analysis
All Platforms:
Sample Result:
trade_date | symbol | close_price | month_open | month_close | monthly_return_pct |
|---|---|---|---|---|---|
2024-01-02 | AAPL | 185.50 | 185.50 | 190.25 | 2.56 |
2024-01-03 | AAPL | 187.20 | 185.50 | 190.25 | 2.56 |
... | AAPL | ... | 185.50 | 190.25 | 2.56 |
2024-01-31 | AAPL | 190.25 | 185.50 | 190.25 | 2.56 |
Example 5: Customer Lifetime Value Tracking
All Platforms:
Example 6: Running vs Period Comparisons
All Platforms:
Window Frame Importance
Default Frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW):
FIRST_VALUE: Works correctly (always gets first)
LAST_VALUE: Gets current row, NOT actual last! ❌
NTH_VALUE: May not reach desired position
Correct Frame for LAST_VALUE:
Common Use Cases
FIRST_VALUE: Baseline comparisons, cohort analysis
LAST_VALUE: Period-end values, final status
NTH_VALUE: Percentile values, top-N access
Combined: Opening/closing prices, start/end comparisons
Performance Tips
Partition wisely: Smaller partitions = faster processing
Reuse window definitions: Define once, reference multiple times
Index ORDER BY columns: Improves sorting performance
Consider materialized views: For frequently used calculations
Limit frame size: UNBOUNDED can be expensive
Best Practices
Always specify frame for LAST_VALUE: Avoid default frame confusion
Use appropriate frame: ROWS vs RANGE
Handle NULLs: Consider IGNORE NULLS clause (Snowflake)
Document window logic: Explain frame and partition choices
Test edge cases: Empty partitions, single rows
Reuse window definitions:
WINDOW w AS (PARTITION BY ... ORDER BY ...)





