All questions from the Data Analyst interview pack (DAint). Try writing your SQL in the green “Try your SQL” boxes and use "Reveal answer" if you're stuck. Validate checks your result (we're lenient on spacing and show accuracy if you're close).
Input table: Employees
| EmpID | Name | Salary |
|---|---|---|
| 1 | Alice | 60000 |
| 2 | Bob | 80000 |
| 3 | Charlie | 75000 |
| 4 | David | 80000 |
| 5 | Eve | 90000 |
Expected output: Second_Highest_Salary = 80000
Input table: Orders
| OrderID | OrderDate | Revenue |
|---|---|---|
| 101 | 2024-01-01 | 100 |
| 102 | 2024-01-01 | 200 |
| 103 | 2024-01-02 | 150 |
| 104 | 2024-01-03 | 300 |
| 105 | 2024-01-03 | 100 |
In the try-it below (SQLite), use a CTE: first SELECT OrderDate, SUM(Revenue) AS Daily_Revenue ... GROUP BY OrderDate, then SUM(Daily_Revenue) OVER (ORDER BY OrderDate) in the outer query.
Input table: Employees
| EmpID | Name | Salary | ManagerID |
|---|---|---|---|
| 1 | Alice | 70000 | NULL |
| 2 | Bob | 80000 | 1 |
| 3 | Charlie | 60000 | 1 |
| 4 | David | 90000 | 2 |
| 5 | Eve | 85000 | 2 |
Output: Bob 80000, David 90000, Eve 85000.
Tables: Products (ProductID, ProductName); OrderItems (OrderID, ProductID, Quantity). Sample: Products 1–4 (Shoes, Bag, Watch, Hat); OrderItems has 101→1, 102→3, 103→1.
Output: 2 Bag, 4 Hat.
Input: Employees (EmpID, EmpName, Department, Salary). Goal: list employees whose salary matches someone else’s in the same department.
Input: Purchases (CustomerID, CustomerName, PurchaseAmount). Goal: top N distinct purchase amounts and corresponding customers. N=2 → Bob 7000, Charlie 7000, David 6500.
Use RANK() so ties all get rank 1. ROW_NUMBER() would pick only one row per customer.
Middle value (odd count) or average of two middle values (even count).
Use ROW_NUMBER; then LoginDate − rn gives a constant for consecutive days. Group by UserID and that constant, then HAVING COUNT(*) ≥ 3.
Extract year-month, use LAG/LEAD to get prev/next month; filter where prev is consecutive and next has a gap.
MySQL/Postgres: DELETE WHERE CustomerID NOT IN (SELECT MIN(CustomerID) FROM Customers GROUP BY Name, Email). With CTE (Postgres):
Techniques: (1) Add indexes on JOIN and WHERE columns. (2) Use EXPLAIN ANALYZE to find full scans and missing indexes. (3) Avoid SELECT *; project only needed columns. (4) Use CTEs or temp tables for intermediate results. (5) Join smaller filtered sets first. (6) Partitioning and batch deletes/inserts. (7) Materialized views or summary tables for precomputed aggregations. (8) Prefer window functions over correlated subqueries where applicable.
Without LIMIT: use a CTE with RANK() OVER (ORDER BY TotalSalary DESC) and WHERE rnk = 1.
Use MONTH(SaleDate) or EXTRACT(MONTH FROM SaleDate) in MySQL/Postgres.