pandas & SQL — problem bank
rapid revision, not a tutorial · each card: approach in one line + code you can type from memory
PY pandas
groupby aggregations
group by key(s), use named aggregation to keep column names flat
df.groupby('dept').agg(
avg_sal=('salary','mean'),
max_sal=('salary','max')
).reset_index()
- named agg avoids the messy MultiIndex columns
- .agg({'col':['mean','max']}) for quick multi-func on one col
- always .reset_index() after, for a flat df
pivoting
long→wide: pivot_table (auto-aggregates dupes). wide→long: melt
df.pivot_table(index='date', columns='cat',
values='sales', aggfunc='sum')
df.melt(id_vars='date', var_name='cat',
value_name='sales')
- plain .pivot() errors on duplicate index/col combos — pivot_table handles it
- melt is the exact reverse of pivot
handling duplicates
inspect with duplicated(), remove with drop_duplicates()
df[df.duplicated(subset=['id'], keep=False)]
df.drop_duplicates(subset=['id'], keep='first')
- keep=False flags every copy — inspect before you drop
- always pass subset= explicitly, don't rely on full-row match
merging datasets
pick join type by what rows to keep, validate with indicator
df1.merge(df2, on='id', how='left',
indicator=True)
- how='left' keeps all df1 rows, NaN-fills missing matches
- indicator=True adds a _merge col — great for debugging row-count surprises
- watch for duplicate keys on either side silently multiplying rows
rolling window calculations
sort by time first, then rolling().agg(), group for per-entity windows
df.sort_values('date')
.groupby('store')['sales']
.rolling(7).mean()
- rolling() needs sorted data — sort_values on the time col first, always
- min_periods= avoids NaNs at the start if partial windows are fine
SQL sql
nth highest value
DENSE_RANK() over ORDER BY, filter rnk = N — handles ties correctly
SELECT salary FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) rnk
FROM employees
) t WHERE rnk = 2;
- DENSE_RANK skips no numbers on ties (1,1,2) — use RANK() for gaps instead
- LIMIT 1 OFFSET 1 is shorter but silently wrong when there are ties
running totals
SUM() as a window function ordered by the sequence column
SELECT order_date, amount,
SUM(amount) OVER (ORDER BY order_date)
AS running_total
FROM orders;
- window function, not GROUP BY — keeps every row instead of collapsing
- add PARTITION BY customer_id for a running total per group
duplicate detection
GROUP BY the key, HAVING COUNT(*) > 1
SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
- HAVING filters after aggregation — WHERE can't reference COUNT()
- to get the actual duplicate rows back, join this result to the base table
date-based joins
join on a date range (BETWEEN) instead of exact equality
SELECT o.order_id, p.price
FROM orders o
JOIN prices p
ON o.product_id = p.product_id
AND o.order_date
BETWEEN p.start_date AND p.end_date;
- exact-equality joins fail when tables have different date granularity — range join fixes it
- overlapping ranges can produce duplicate matches — sanity-check row count after
before the interview
say the one-line approach out loud first, then write code — interviewers grade the reasoning, not just syntax. if stuck, name the pattern (window function / groupby / range join) even before you remember exact syntax.