Skip to main content
📘 Complete PDF

PySpark Certification Practice Test 04

Window Functions and Analytical Processing

Question 1 of 20
📋 Multiple Choice
Question 61
An interviewer says: "A retail company wants the latest order for every customer. The source table contains multiple orders per customer." Which function would most likely be used?
✓
A. row_number()
B. count()
C. distinct()
D. sum()
Answer
✅ A. row_number()
Explanation

1. Core Concept In relational algebra and distributed query engines, isolating the single latest or earliest event per entity requires assigning a sequential integer to rows within partitioned groups based on a chronological order. In PySpark, **`row_number()`** is the standard window function used to number rows deterministically from 1 to $N$ per partition.

2. Detailed Breakdown In PySpark: - Syntax:

  from pyspark.sql.window import Window
  from pyspark.sql.functions import row_number, desc

  windowSpec = Window.partitionBy("customer_id").orderBy(desc("order_date"))
  df.withColumn("rn", row_number().over(windowSpec)).filter("rn = 1")
  • Catalyst & Physical Plan: - Spark plans a WindowExec physical operator. - Rows are shuffled across cluster nodes partitioned by hash(customer_id) % shuffle.partitions using an Exchange hashpartitioning. - Within each partition, rows are sorted in descending order by order_date via Sort [customer_id ASC, order_date DESC]. - row_number() maintains an internal counter that increments by 1 for every record in the partition, resetting to 1 whenever the customer_id changes. - Filtering for rn = 1 isolates exactly one newest record per customer.

3. Why the Correct Answer is Correct The interviewer requirement specifies: *"the latest order for every customer"* where multiple orders exist. - Grouping by customer and ordering by order date descending allows `row_number()` to assign rank 1 to the most recent order. - Filtering by `row_number == 1` returns the exact latest record for every customer. - Therefore, option A is the standard and correct function.

4. Why Each Distractor is Incorrect - **B (count()):** Computes the total number of orders placed by the customer; it cannot identify or extract the latest order record. - **C (distinct()):** Deduplicates identical rows across all columns; it does not sort by timestamp or isolate the newest record. - **D (sum()):** Computes the arithmetic total of numeric values (e.g. order totals); it has no temporal ordering or ranking capability.

5. Code Example

from pyspark.sql import SparkSession
from pyspark.sql.window import Window
from pyspark.sql.functions import row_number, desc, col

spark = SparkSession.builder.appName("LatestOrderDemo").getOrCreate()

orders = [
    (101, "ORD_01", "2023-01-15", 50.0),
    (101, "ORD_02", "2023-03-20", 120.0), # Latest for 101
    (102, "ORD_03", "2023-02-10", 80.0),  # Only order for 102
    (103, "ORD_04", "2023-01-05", 210.0),
    (103, "ORD_05", "2023-04-12", 45.0)   # Latest for 103
]
df = spark.createDataFrame(orders, ["customer_id", "order_id", "order_date", "amount"])

# Define window partitioned by customer, sorted by date descending
window_spec = Window.partitionBy("customer_id").orderBy(desc("order_date"))

latest_orders = (
    df.withColumn("rn", row_number().over(window_spec))
      .filter(col("rn") == 1)
      .drop("rn")
)
latest_orders.show()
# +-----------+--------+----------+------+
# |customer_id|order_id|order_date|amount|
# +-----------+--------+----------+------+
# |        101|  ORD_02|2023-03-20| 120.0|
# |        102|  ORD_03|2023-02-10|  80.0|
# |        103|  ORD_05|2023-04-12|  45.0|
# +-----------+--------+----------+------+

6. Key Takeaway To extract the latest, earliest, or top-1 record per entity, partition by entity ID, order descending by timestamp, and filter for `row_number() == 1`.

7. Production Best Practice If timestamps can tie (two orders placed at the exact same second), `row_number()` will non-deterministically pick one unless a secondary tie-breaker column (such as `order_id`) is added to the `orderBy()` clause: `Window.partitionBy("customer_id").orderBy(desc("order_date"), desc("order_id"))`.

8. Real-World Engineering Scenario In Slowly Changing Dimension Type 1 (SCD1) or CDC (Change Data Capture) ingestion pipelines, upstream database replication logs emit multiple inserts, updates, and deletes for the same primary key. Data engineers deduplicate the stream by partitioning by primary key, ordering by CDC timestamp descending, and filtering for `row_number() == 1` to retain the current state.

9. Common Pitfall / Anti-Pattern Attempting to get the latest record by doing `df.groupBy("customer_id").agg(max("order_date"))` and then inner-joining back to the raw table. This requires two full cluster shuffles and an expensive join, whereas `row_number()` achieves the same result in a single shuffle pass.

10. Tutorial Reference Master windowing and ranking techniques in [PySpark DataFrame Window Functions](/tutorials/pyspark/df-window-functions).

Answered: 0 / 20
Question Navigator (Test 04)0% Answered