Bird
Raised Fist0
PostgreSQLquery~10 mins

FIRST_VALUE and LAST_VALUE in PostgreSQL - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - FIRST_VALUE and LAST_VALUE
Start with ordered data
↓
Apply window function
↓
FIRST_VALUE: pick first row value in window
↓
LAST_VALUE: pick last row value in window
↓
Return result for each row
These functions look at a set of rows ordered in a window and return the first or last value from that set for each row.
Execution Sample
PostgreSQL
SELECT id, value,
  FIRST_VALUE(value) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_val,
  LAST_VALUE(value) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_val
FROM sample_table
ORDER BY id;
This query shows how FIRST_VALUE and LAST_VALUE return the first and last 'value' in the ordered rows by 'id'.
Execution Table
StepRow idvalueWindow FrameFIRST_VALUE(value)LAST_VALUE(value)
1110[1..1]1010
2220[1..2]1020
3330[1..3]1030
4440[1..4]1040
5550[1..5]1050
💡 All rows processed; window frame moves with each row; FIRST_VALUE always first row's value; LAST_VALUE depends on frame definition.
Variable Tracker
VariableStartAfter Row 1After Row 2After Row 3After Row 4After Row 5
FIRST_VALUE(value)N/A1010101010
LAST_VALUE(value)N/A1020304050
Key Moments - 2 Insights
Why does LAST_VALUE sometimes not return the last value you expect?
Because LAST_VALUE depends on the window frame. Without specifying ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, the frame ends at the current row, so LAST_VALUE returns the current row's value, not the last in the entire partition.
Does FIRST_VALUE change as we move through rows?
No, FIRST_VALUE always returns the first value in the window frame, which usually starts at the first row, so it stays the same for all rows.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is FIRST_VALUE(value) at row id 3?
A20
B30
C10
D40
💡 Hint
Check the FIRST_VALUE(value) column for row id 3 in the execution_table.
At which row does LAST_VALUE(value) change from 30 to 40?
ARow 2
BRow 4
CRow 3
DRow 5
💡 Hint
Look at the LAST_VALUE(value) column in the execution_table and find where it changes.
If the window frame for LAST_VALUE was not set to UNBOUNDED FOLLOWING, what would LAST_VALUE return at row 5?
A50
B40
C10
DN/A
💡 Hint
Consider that without UNBOUNDED FOLLOWING, the frame ends at the current row, so LAST_VALUE returns the current row's value.
Concept Snapshot
FIRST_VALUE(value) returns the first value in the ordered window.
LAST_VALUE(value) returns the last value in the window frame.
Window frame defaults affect LAST_VALUE results.
Use ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING for full partition.
Both functions return a value for each row in the result.
Full Transcript
This lesson shows how FIRST_VALUE and LAST_VALUE work in PostgreSQL. We start with data ordered by id. FIRST_VALUE always picks the first value in the window, so it stays the same for all rows. LAST_VALUE picks the last value in the window frame, which depends on how the frame is defined. If the frame ends at the current row, LAST_VALUE returns the current row's value. To get the last value of the entire partition, we set the frame to include all rows from the start to the end. The execution table shows these values step by step for each row. Understanding window frames is key to using LAST_VALUE correctly.

Practice

(1/5)
1. What does the FIRST_VALUE function do in PostgreSQL?
easy
A. Returns the first value in a sorted group of rows.
B. Returns the last value in a sorted group of rows.
C. Returns the average value of a column.
D. Returns the total count of rows.

Solution

  1. Step 1: Understand the purpose of FIRST_VALUE

    FIRST_VALUE returns the first value in a sorted window or group of rows.
  2. Step 2: Compare with other options

    Options B, C, and D describe different functions or aggregates, not FIRST_VALUE.
  3. Final Answer:

    Returns the first value in a sorted group of rows. -> Option A
  4. Quick Check:

    FIRST_VALUE = first value in sorted rows [OK]
Hint: FIRST_VALUE always picks the first row's value in order [OK]
Common Mistakes:
  • Confusing FIRST_VALUE with LAST_VALUE
  • Thinking it returns an aggregate like sum or count
  • Ignoring the sorting order in the window
2. Which of the following is the correct syntax to get the last value of a column score ordered by date using LAST_VALUE in PostgreSQL?
easy
A. SELECT LAST_VALUE(score) FROM results ORDER BY date;
B. SELECT LAST_VALUE(score) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM results;
C. SELECT LAST_VALUE(score) OVER (PARTITION BY date) FROM results;
D. SELECT LAST_VALUE(score) OVER (ORDER BY date) FROM results;

Solution

  1. Step 1: Understand LAST_VALUE default frame

    LAST_VALUE by default looks from current row to end, so it may not return the last value overall without framing.
  2. Step 2: Use explicit window frame to get true last value

    Adding ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ensures the entire partition is considered.
  3. Final Answer:

    SELECT LAST_VALUE(score) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM results; -> Option B
  4. Quick Check:

    LAST_VALUE needs full frame to get last value [OK]
Hint: Add full window frame to LAST_VALUE for correct last row [OK]
Common Mistakes:
  • Omitting window frame causing wrong last value
  • Using PARTITION BY incorrectly
  • Using LAST_VALUE without OVER() clause
3. Given the table sales with columns region, month, and revenue, what will this query return?
SELECT region, month, revenue, FIRST_VALUE(revenue) OVER (PARTITION BY region ORDER BY month) AS first_rev FROM sales ORDER BY region, month;
medium
A. The total revenue summed for each region.
B. The revenue of the last month for each region repeated on every row of that region.
C. The revenue of the first month for each region repeated on every row of that region.
D. The revenue of the current month only.

Solution

  1. Step 1: Analyze FIRST_VALUE with PARTITION and ORDER BY

    FIRST_VALUE(revenue) OVER (PARTITION BY region ORDER BY month) returns the first revenue value per region ordered by month.
  2. Step 2: Understand output per row

    For each row in a region, the first month's revenue is repeated as first_rev.
  3. Final Answer:

    The revenue of the first month for each region repeated on every row of that region. -> Option C
  4. Quick Check:

    FIRST_VALUE repeats first row's value per partition [OK]
Hint: FIRST_VALUE repeats first sorted value per group [OK]
Common Mistakes:
  • Thinking it returns last value instead
  • Assuming it sums or aggregates
  • Ignoring PARTITION BY effect
4. You wrote this query but it returns unexpected results:
SELECT employee_id, salary, LAST_VALUE(salary) OVER (ORDER BY employee_id) AS last_sal FROM employees;

What is the likely cause?
medium
A. LAST_VALUE cannot be used without PARTITION BY clause.
B. ORDER BY employee_id is invalid in window functions.
C. salary column must be aggregated with SUM before LAST_VALUE.
D. LAST_VALUE needs a window frame to include all rows; default frame causes wrong output.

Solution

  1. Step 1: Recall LAST_VALUE default frame behavior

    By default, LAST_VALUE looks from current row to end, so it may not return the last row's value overall.
  2. Step 2: Identify missing window frame

    Without specifying ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING, the last value is not the last row's value.
  3. Final Answer:

    LAST_VALUE needs a window frame to include all rows; default frame causes wrong output. -> Option D
  4. Quick Check:

    LAST_VALUE requires full frame for correct last row [OK]
Hint: Add full frame to LAST_VALUE to fix wrong results [OK]
Common Mistakes:
  • Assuming ORDER BY alone fixes LAST_VALUE
  • Thinking PARTITION BY is mandatory
  • Trying to aggregate salary before LAST_VALUE
5. You want to find the first and last sale amount for each customer ordered by sale date. Which query correctly returns both values per customer in PostgreSQL?
hard
A. SELECT customer_id, sale_date, sale_amount, FIRST_VALUE(sale_amount) OVER (PARTITION BY customer_id ORDER BY sale_date), LAST_VALUE(sale_amount) OVER (PARTITION BY customer_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM sales;
B. SELECT customer_id, sale_date, sale_amount, FIRST_VALUE(sale_amount), LAST_VALUE(sale_amount) FROM sales GROUP BY customer_id;
C. SELECT customer_id, sale_date, sale_amount, FIRST_VALUE(sale_amount) OVER (ORDER BY sale_date), LAST_VALUE(sale_amount) OVER (ORDER BY sale_date) FROM sales;
D. SELECT customer_id, sale_date, sale_amount, MIN(sale_amount) OVER (PARTITION BY customer_id), MAX(sale_amount) OVER (PARTITION BY customer_id) FROM sales;

Solution

  1. Step 1: Use FIRST_VALUE with PARTITION and ORDER BY

    FIRST_VALUE(sale_amount) OVER (PARTITION BY customer_id ORDER BY sale_date) gets first sale per customer.
  2. Step 2: Use LAST_VALUE with full window frame

    LAST_VALUE needs ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING to get last sale per customer.
  3. Step 3: Check other options

    SELECT customer_id, sale_date, sale_amount, FIRST_VALUE(sale_amount), LAST_VALUE(sale_amount) FROM sales GROUP BY customer_id; lacks OVER() and ORDER BY, C lacks PARTITION BY, D uses MIN/MAX which is different.
  4. Final Answer:

    SELECT customer_id, sale_date, sale_amount, FIRST_VALUE(sale_amount) OVER (PARTITION BY customer_id ORDER BY sale_date), LAST_VALUE(sale_amount) OVER (PARTITION BY customer_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM sales; -> Option A
  5. Quick Check:

    Combine FIRST_VALUE and LAST_VALUE with proper framing [OK]
Hint: Use full frame for LAST_VALUE with PARTITION and ORDER BY [OK]
Common Mistakes:
  • Omitting window frame for LAST_VALUE
  • Using aggregate functions instead of window functions
  • Not partitioning by customer_id
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard