← PayPal Interview Insights

PayPal·Data Scientist·Technical Phone Screen·Intermediate

Intermediate
May 2026

Summary

PayPal data scientist screen, SQL and Python heavy. They gave you a transactions table and worked through a bunch of concepts back to back, felt more like a technical quiz than a real conversation.

Questions Asked (6)

Q1

What are window functions and what are some common use cases for them?

Product Analytics & MetricsAlgorithms & Data Structures
Author's notes

Went fine, covered running totals, ranking rows within partitions, lag/lead for time-series comparisons.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start with a clear, concise definition of window functions, emphasizing their ability to perform calculations across a set of rows while retaining individual row details. Then, explain the key components (OVER clause, PARTITION BY, ORDER BY) and provide concrete use cases relevant to data science and PayPal, such as calculating running totals, rankings, and moving averages. Finally, contrast them with GROUP BY to highlight their unique value.

Pro tip: Mention that window functions are often more efficient than self-joins or subqueries for these tasks, and give an example of how they can be used to compute customer lifetime value or detect fraudulent patterns at PayPal.

1. Define window functions

Explain that window functions perform calculations across a set of table rows related to the current row, without collapsing them into a single output row like aggregate functions.

2. Explain syntax and components

Describe the OVER clause, PARTITION BY for grouping, ORDER BY for ordering within partitions, and the frame specification (e.g., ROWS BETWEEN).

3. List common use cases

Provide examples such as running totals, moving averages, ranking (ROW_NUMBER, RANK, DENSE_RANK), lag/lead analysis, and percentiles.

4. Relate to data science and PayPal

Connect use cases to real-world scenarios: calculating customer lifetime value, detecting anomalies in transaction data, cohort analysis, and time-series forecasting.

5. Compare with alternatives

Highlight advantages over GROUP BY, self-joins, or subqueries, such as simplicity, performance, and ability to retain row-level detail.

Key Points to Mention

  • Definition: window functions operate on a set of rows and return a value for each row, unlike aggregate functions that return a single value per group.
  • Key clauses: OVER(), PARTITION BY, ORDER BY, and frame specification (ROWS/RANGE BETWEEN).
  • Common functions: ROW_NUMBER(), RANK(), DENSE_RANK(), LAG(), LEAD(), SUM(), AVG(), NTILE().
  • Use cases: running totals, moving averages, ranking, percentiles, and comparing values across rows (e.g., month-over-month growth).
  • Difference from GROUP BY: window functions do not collapse rows, allowing simultaneous access to individual row details and aggregated values.
  • Performance considerations: often more efficient than self-joins or correlated subqueries for these calculations.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Explain the difference between INNER, LEFT, RIGHT, FULL OUTER, and CROSS joins.

Data Modeling
Author's notes

Standard stuff.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining what a join does: combining rows from two tables based on a related column. Then explain each join type in terms of which rows are included in the result set, using a simple example like customers and orders. Finally, highlight the practical implications for data analysis, such as how LEFT JOIN preserves all rows from the left table and how CROSS JOIN produces a Cartesian product.

Pro tip: Mention that in practice, INNER JOIN is the most common, but LEFT JOIN is crucial for finding missing relationships (e.g., customers without orders). Also, note that FULL OUTER JOIN is not supported in MySQL, so you might use UNION of LEFT and RIGHT joins as a workaround.

1. Define Joins

Briefly explain that joins combine rows from two or more tables based on a related column, and that the join type determines which rows are included.

2. Explain Each Join Type

For each join (INNER, LEFT, RIGHT, FULL OUTER, CROSS), describe which rows from the left and right tables are included in the result. Use a simple example (e.g., customers and orders) to illustrate.

3. Use a Visual or Tabular Representation

If possible, sketch Venn diagrams or describe the result set in terms of matching and non-matching rows. This helps clarify the differences.

4. Discuss Use Cases

Explain when each join is appropriate. For example, INNER JOIN for matching records, LEFT JOIN for preserving all left records, FULL OUTER for preserving all records from both sides, and CROSS JOIN for generating combinations.

5. Mention Performance and Practical Considerations

Note that CROSS JOIN can produce large result sets and should be used cautiously. Also, mention that FULL OUTER JOIN may not be supported in all databases (e.g., MySQL) and how to emulate it.

Key Points to Mention

  • INNER JOIN returns only rows with matching keys in both tables.
  • LEFT JOIN returns all rows from the left table and matching rows from the right; unmatched right rows get NULLs.
  • RIGHT JOIN is the opposite of LEFT JOIN: all rows from the right table and matching from the left.
  • FULL OUTER JOIN returns all rows from both tables, with NULLs where there is no match.
  • CROSS JOIN returns the Cartesian product of the two tables (all possible combinations).
  • Practical tip: Use LEFT JOIN to find missing relationships (e.g., customers without orders) by filtering for NULLs in the right table.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

What is the difference between RANK() and DENSE_RANK()?

Algorithms & Data StructuresProduct Analytics & Metrics
Author's notes

The classic gotcha.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining both functions as window functions that assign ranks based on an ORDER BY clause. Then highlight the key difference: RANK() leaves gaps in the ranking sequence after ties, while DENSE_RANK() does not. Use a concrete example with duplicate values to illustrate the difference, and mention how this impacts downstream analysis.

Pro tip: In interviews, always relate window functions to real business scenarios. For example, at PayPal, you might rank merchants by transaction volume; using DENSE_RANK() ensures no gaps, which is crucial when selecting top N distinct ranks for tiered rewards.

1. Define both functions

State that RANK() and DENSE_RANK() are window functions that assign a rank to each row based on the ORDER BY clause. Both handle ties by assigning the same rank to identical values.

2. Explain the difference

Clarify that RANK() skips ranks after ties (e.g., 1,2,2,4), while DENSE_RANK() does not skip ranks (e.g., 1,2,2,3). The difference lies in how subsequent ranks are calculated.

3. Provide a concrete example

Use a small dataset with duplicate values to show the output of both functions side by side. For instance, scores: 100, 100, 90, 80 yields RANK: 1,1,3,4 and DENSE_RANK: 1,1,2,3.

4. Discuss implications and use cases

Explain when to use each: RANK() for competitions where ties skip positions, DENSE_RANK() for scenarios requiring consecutive ranks like top N per group without gaps.

Key Points to Mention

  • Both are window functions that require an ORDER BY clause.
  • RANK() produces gaps in ranking after ties; DENSE_RANK() does not.
  • Example: values 10, 20, 20, 30 -> RANK: 1,2,2,4; DENSE_RANK: 1,2,2,3.
  • Use RANK() when you want to reflect the number of preceding rows (e.g., Olympic medals).
  • Use DENSE_RANK() when you need consecutive ranks for filtering top N distinct values.
  • Other window functions like ROW_NUMBER() always assign unique ranks without ties.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Write a SQL query that calculates total GMV grouped by merchant.

Product Analytics & MetricsData Modeling
Author's notes

Basic GROUP BY with SUM on amount.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the definition of GMV and the grain of the data, then write a straightforward SQL query that sums transaction amounts grouped by merchant. Show awareness of edge cases like refunds, cancellations, and time zones, and explain how you would validate the result.

Pro tip: Mention that GMV should typically exclude cancelled or returned orders and that you would confirm with stakeholders whether to include tax, shipping, or discounts. Also, suggest adding a date filter to avoid full-table scans in production.

1. Clarify requirements

Ask clarifying questions about the definition of GMV (e.g., gross vs. net, inclusion of refunds, time period) and the expected output grain (one row per merchant).

2. Identify tables and columns

Determine which tables contain transaction data and merchant identifiers, and confirm the column that represents the monetary value for GMV.

3. Write the SQL query

Construct a query using SUM(amount) and GROUP BY merchant_id, applying any necessary filters (e.g., status = 'completed') and handling NULLs.

4. Validate and optimize

Check for data quality issues, consider indexing or partitioning for performance, and validate results against a known total or sample.

5. Explain and iterate

Walk through the query logic, discuss assumptions, and suggest how to adapt if requirements change (e.g., adding time granularity).

Key Points to Mention

  • Definition of GMV: typically total sales value of goods or services, excluding returns and cancellations.
  • Handling of refunds, cancellations, and failed transactions: filter by status or use conditional aggregation.
  • Time period filtering: use a WHERE clause on transaction date to limit scope and improve performance.
  • Grouping by merchant: use merchant_id or merchant_name, and consider whether to include merchants with zero GMV.
  • Data types and NULL handling: ensure numeric columns are summed correctly and NULLs are treated as zero or excluded.
  • Performance considerations: indexing on merchant_id and date, avoiding SELECT *, and using appropriate aggregation functions.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Write a SQL query that returns each user's list of merchants as a single comma-separated string, handling any type casting between DECIMAL and STRING where needed.

Data ModelingAlgorithms & Data Structures
Author's notes

This one tripped me up more than it should have.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the table schema and the desired output format, then use an aggregate function like STRING_AGG or GROUP_CONCAT to concatenate merchant names per user. Explicitly handle type casting (e.g., CAST(amount AS STRING)) if the merchant column is numeric, and ensure proper ordering and delimiter handling.

Pro tip: Mention that you would check for NULLs and duplicates before aggregating, and use DISTINCT inside the aggregate function if needed to avoid repeated merchants. Also, note that the exact function name depends on the SQL dialect (e.g., STRING_AGG in PostgreSQL, GROUP_CONCAT in MySQL), showing awareness of portability.

1. Clarify requirements and schema

Ask about the table structure, the column containing merchant identifiers, and whether the output should be sorted or deduplicated. Confirm the SQL dialect to choose the correct string aggregation function.

2. Handle data types and NULLs

If the merchant column is numeric (e.g., DECIMAL), cast it to STRING using CAST or CONVERT. Filter out NULL merchant values to avoid 'NULL' appearing in the concatenated string.

3. Aggregate merchants per user

Use GROUP BY user_id and an aggregate function like STRING_AGG(merchant, ', ') or GROUP_CONCAT(merchant SEPARATOR ', ') to combine merchant values into a single string.

4. Order and deduplicate if needed

If the order matters, include an ORDER BY clause inside the aggregate function (if supported). Use DISTINCT inside the aggregate to remove duplicate merchants.

5. Test and validate

Run the query on a sample dataset to verify the output format, check for edge cases like users with no merchants, and ensure performance is acceptable for large datasets.

Key Points to Mention

  • Use of STRING_AGG (PostgreSQL) or GROUP_CONCAT (MySQL) for string aggregation.
  • Explicit CAST or CONVERT to change DECIMAL to STRING when necessary.
  • Handling NULL values with COALESCE or WHERE clause to exclude them.
  • Using DISTINCT inside the aggregate function to avoid duplicate merchants.
  • Ordering the concatenated values with ORDER BY inside the aggregate (if supported).
  • Considering performance implications for large datasets and potential indexing.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

Using Python, iterate over a list of dictionaries representing transaction rows and build a mapping from user_id to their total transaction amount.

Algorithms & Data StructuresProduct Analytics & Metrics
Author's notes

Basically a dict accumulation pattern.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data structure and requirements, then implement a solution using a dictionary to accumulate totals. Use a simple loop or defaultdict for efficiency, and discuss handling edge cases like missing keys or non-numeric values.

Pro tip: Mention that using collections.defaultdict(float) avoids key-checking overhead and is more Pythonic, but also note that for very large datasets, a generator-based approach or pandas groupby might be more scalable.

1. Clarify the problem

Confirm the structure of the list of dictionaries (e.g., keys like 'user_id' and 'amount') and whether amounts are always numeric. Ask about expected size and any edge cases.

2. Choose data structures

Decide between a regular dictionary with manual key checks or collections.defaultdict for cleaner code. Consider if a pandas DataFrame would be more appropriate for large-scale data.

3. Implement the iteration

Write a loop that iterates over each transaction, extracts user_id and amount, and adds the amount to the running total for that user. Handle missing or invalid data gracefully.

4. Test and validate

Test with sample data including edge cases like empty list, missing keys, or negative amounts. Verify that totals are correct and that the function handles unexpected inputs.

5. Discuss scalability and alternatives

Mention how the solution scales and when to use alternatives like pandas groupby or SQL aggregation for very large datasets. Highlight time and space complexity.

Key Points to Mention

  • Use of defaultdict(float) to simplify accumulation and avoid KeyError.
  • Time complexity O(n) and space complexity O(k) where k is number of unique users.
  • Handling edge cases: missing 'user_id' or 'amount' keys, non-numeric amounts, empty input.
  • Alternative approaches: pandas groupby, SQL GROUP BY, or using a Counter for non-numeric aggregation.
  • Pythonic idioms: dictionary comprehension, generator expressions, or using .get() with default.
  • Importance of data validation and type checking in production code.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.