Data Analyst
SQL questions
168 questions on SQL for data analysts, easiest first.
Easy 53
- WHERE vs HAVINGeasy
- Which join keeps all customerseasy
- COUNT(*) vs COUNT(column)easy
- What a pivot table doeseasy
- Finding NULL valueseasy
- COUNT(DISTINCT) with NULLseasy
- Rows from an INNER JOINeasy
- UNION vs UNION ALLeasy
- AVG with a NULL valueeasy
- Bucketing with CASE WHENeasy
- Dividing two integers in SQLeasy
- Why this GROUP BY failseasy
- Does BETWEEN include the endseasy
- Matching text with LIKEeasy
- Top seller with ORDER BY and LIMITeasy
- What a primary key guaranteeseasy
- A date that should not changeeasy
- Days between two dateseasy
- Showing the weekday nameeasy
- Last day of the montheasy
- A running total columneasy
- Showing 0 instead of NULLeasy
- Full name comes out emptyeasy
- Rows from a CROSS JOINeasy
- DISTINCT with two columnseasy
- Column alias in WHERE failseasy
- Sorting by two columnseasy
- Window function vs GROUP BYeasy
- An empty OVER clauseeasy
- What PARTITION BY doeseasy
- RANK values for tied scoreseasy
- Filtering on ROW_NUMBER in WHEREeasy
- LAG on the first roweasy
- What LEAD returnseasy
- Each product's share of saleseasy
- Top 3 products in each categoryeasy
- Second highest salary with tieseasy
- A 3-day moving average frameeasy
- Salary vs department averageeasy
- Each customer's first product boughteasy
- Team size on every employee roweasy
- ORDER BY inside and outside OVEReasy
- Computing PERCENT_RANKeasy
- Computing CUME_DISTeasy
- Highest DENSE_RANK valueeasy
- Deleting duplicate rowseasy
- Total count beside a page of rowseasy
- Window functions in MySQLeasy
- Reusing a window aliaseasy
- Highest balance so fareasy
- Rows with a NULL regioneasy
- Looking two rows aheadeasy
- Sorting by a window valueeasy
Medium 63
- Revenue doubled after a joinmedium
- Latest order per customermedium
- Running total of salesmedium
- LEFT JOIN that lost customersmedium
- RANK vs DENSE_RANK after a tiemedium
- Month-over-month change with LAGmedium
- Share of paid orders in one querymedium
- Customers who never orderedmedium
- Grouping orders by monthmedium
- Counting repeat customers with a CTEmedium
- Rows after a pandas left mergemedium
- SUM over zero matching rowsmedium
- Sum that skips hidden rowsmedium
- Summing a column that has errorsmedium
- Weighted average pricemedium
- Month labels sort in the wrong ordermedium
- One month after 31 Januarymedium
- Working days in two weeksmedium
- Due date 3 working days latermedium
- Age in completed yearsmedium
- January shows two years togethermedium
- Order of CASE branchesmedium
- Customers listed many timesmedium
- Showing each employee's managermedium
- Each region's share of total salesmedium
- Counting paid orders returns all ordersmedium
- Bought in both January and Februarymedium
- Rows from GROUP BY ROLLUPmedium
- ROW_NUMBER in a WHERE clausemedium
- What QUALIFY is formedium
- Running total that resets per customermedium
- Computing a running totalmedium
- Value of a 3-row moving averagemedium
- 7-row average with missing daysmedium
- Splitting clicks into sessionsmedium
- Grouping consecutive datesmedium
- Share of total after GROUP BYmedium
- Previous order from another customermedium
- Best seller per city with tiesmedium
- The third purchase amountmedium
- Running count of distinct customersmedium
- Month-over-month growth valuemedium
- Tagging rows with a cohort monthmedium
- Counting ticket status changesmedium
- Finding missing invoice numbersmedium
- LAG in pandasmedium
- YTD for an April–March yearmedium
- Reusing one window definitionmedium
- Filtering before or after the windowmedium
- A centred 3-day averagemedium
- A date-based 7-day framemedium
- Day-over-day change with gapsmedium
- LAG on raw order rowsmedium
- A window inside a windowmedium
- Year-over-year with LAG 12medium
- Spotting customers who lapsedmedium
- Products making 80% of revenuemedium
- Window function after GROUP BYmedium
- Marking duplicates in an UPDATEmedium
- Speeding up a ranking querymedium
- RANK in pandasmedium
- Latest row with DISTINCT ONmedium
- DISTINCT and a window countmedium
Hard 52
- NOT IN returns nothinghard
- Average of averageshard
- Daily numbers do not matchhard
- Running total with tied dateshard
- Filter inside the ON clausehard
- Not-equal filter loses rowshard
- PERCENTILE_CONT vs PERCENTILE_DISChard
- NTILE with 10 rowshard
- Latest order changes between runshard
- Click-through rate with zero impressionshard
- Adding up daily active usershard
- Filtering NaN with == in pandashard
- GROUP BY with NULL citieshard
- Dates swapped when opening a CSVhard
- The date that never existedhard
- Financial year from a datehard
- Week number of 1 January 2027hard
- First day of the month from any datehard
- Working days with a Friday–Saturday weekendhard
- Monthly total from a date columnhard
- 7-day average over missing dayshard
- March total misses the last dayhard
- SUM(DISTINCT) gives a low totalhard
- Customers who bought every item in a sethard
- Month-1 retention for a cohorthard
- Subquery returns more than one rowhard
- NULL score ranked firsthard
- Every share shows 0hard
- LAG default vs COALESCEhard
- Forward-filling missing priceshard
- Streaks broken by repeat loginshard
- Runs of the same machine statushard
- Merging overlapping bookingshard
- Largest fall from a peakhard
- PRECEDING with a descending orderhard
- Running totals in an incremental modelhard
- Spark window with no partitionhard
- Average of everyone else in the teamhard
- GROUPS frame with tied dateshard
- Percent of total with LIMIT 10hard
- End dates for history rowshard
- Equal scores in different quartileshard
- A slow filter on a window viewhard
- Order count of zero after a LEFT JOINhard
- Users with a 3-day streakhard
- One partition takes all the timehard
- Five windows, five sortshard
- Products within ₹500 of each pricehard
- What EXCLUDE TIES removeshard
- Median per department in PostgreSQLhard
- Last known value with IGNORE NULLShard
- Ties that are not quite tieshard