LeetCode SQL Problems: 249 Questions With Solutions

LeetCode's SQL track is a separate problem set from the algorithm one. Instead of a function to write you get two or three tables and a question about them, and the answer is a single query checked against a fixed set of rows — there is no data structure to choose and nothing to hand-optimise, so the whole difficulty is in saying the question in SQL.

It is the set to work through if you are interviewing for a data analyst, analytics engineer, data engineer or backend role where a live SQL screen is part of the loop, and it rewards the effort faster than the algorithm track does for one reason: the vocabulary is small and finite. A WHERE clause with an ORDER BY, aggregation with GROUP BY and HAVING, a self-join, a ranking window function, a correlated subquery, date arithmetic, NULL semantics, and CASE — those 8 shapes account for every problem featured on this page. Once you can tell on sight which one a question is asking for, most of the Easy and Medium problems are five lines.

  • 249 problems
  • 100 Easy
  • 105 Medium
  • 44 Hard
  • 8 query shapes

How LeetCode SQL problems break down

A SQL problem does not have an algorithm, it has a shape — the arrangement of clauses that answers the question being asked. There are not many of them, they compose, and the harder problems are two or three of them stacked rather than anything new. Each one below is written out with the signals that give it away and a short query you can read in one sitting. The snippets are MySQL; the only thing that changes between dialects is the date arithmetic, and that difference is stated where it comes up.

  1. 1Filtering and ordering one table
  2. 2Aggregation with GROUP BY and HAVING
  3. 3Self-joins
  4. 4Window functions: RANK, DENSE_RANK and ROW_NUMBER
  5. 5Correlated subqueries
  6. 6Date arithmetic
  7. 7NULL handling
  8. 8Pivoting with CASE

Filtering and ordering one table

One table, a WHERE clause and an ORDER BY — the shape most of the Easy problems reduce to.

This is the base case, and it is worth getting exactly right because every other shape is built on top of it. The clauses are evaluated in a fixed order — FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT — and that order explains most of the errors people hit on the way in. An alias defined in the SELECT list is invisible to WHERE, because WHERE ran first, but it is visible to ORDER BY, which ran last. LIMIT applies after the ordering, so "the second highest" is LIMIT 1 OFFSET 1 rather than LIMIT 2, and wrapping that query in an outer SELECT is the standard way to return NULL instead of an empty result when there is no second row. DISTINCT applies to the whole select list rather than to the column it happens to sit in front of, so adding one more column to the projection can silently un-deduplicate the result.

When it is the answer
  • The question names one table and asks for the rows that match a condition.
  • The answer is the nth largest or smallest value of a single column.
  • Rows have to be de-duplicated before anything else happens to them.
  • The condition is arithmetic on a column: an odd id, a threshold, a remainder.
Filtering and ordering one table — the query
SELECT name, population, area
FROM   World
WHERE  area >= 3000000 OR population >= 25000000
ORDER  BY population DESC
LIMIT  1 OFFSET 1;   -- skip one, take one: the second row, not the top two

Practise it on 176. Second Highest Salary, 595. Big Countries, 620. Not Boring Movies.

Aggregation with GROUP BY and HAVING

Collapse rows into one row per group, then filter the groups.

GROUP BY replaces the rows with one row per distinct value of the grouping key, and every column in the SELECT list then has to be either part of that key or wrapped in an aggregate — anything else is a value picked arbitrarily out of the group, which strict engines reject and lenient ones answer wrongly without telling you. The clause that is misused most is HAVING: WHERE filters rows before the grouping happens, HAVING filters groups after it, so "customers with more than one order" is a HAVING and "orders placed in 2024" is a WHERE. Both belong in the same query more often than not, because filtering the rows first leaves less to group. The other distinction worth memorising is COUNT(*) against COUNT(column): the first counts rows, the second counts rows where that column is not NULL, and on the outer side of a LEFT JOIN those two numbers are different by exactly the amount that matters.

When it is the answer
  • The question is per-something: per customer, per day, per department.
  • The condition is on a count, a sum or an average rather than on a column.
  • Duplicates have to be found — group by the thing that repeats, then HAVING COUNT(*) > 1.
  • The answer is "the one with the most": group, order by the aggregate, take one.
Aggregation with GROUP BY and HAVING — the query
SELECT   customer_id, COUNT(*) AS orders
FROM     Orders
WHERE    status = 'paid'      -- filters ROWS, before grouping
GROUP BY customer_id
HAVING   COUNT(*) > 1         -- filters GROUPS, after
ORDER BY orders DESC
LIMIT    1;

Practise it on 182. Duplicate Emails, 511. Game Play Analysis I, 570. Managers with at Least 5 Direct Reports and 7 more below.

Self-joins

Join a table to itself so that two of its rows can be compared side by side.

SQL compares columns within a row and never rows with each other, so any question of the form "this row against that row" has to put both rows on one line first — which is all a self-join does. The mechanics are just aliases: name the table twice and let the join condition say how the two copies relate, whether that is e.managerId = m.id for a hierarchy, b.id = a.id + 1 for the next row, or ABS(a.x - b.x) = 1 for a neighbour. Two things go wrong reliably. An equality self-join matches every row with itself, so a comparison on the key (a.id < b.id) is usually needed both to drop those self-pairs and to keep each real pair once instead of twice. And joining consecutive rows on id + 1 is only correct if the ids really are consecutive — the moment rows can be deleted, the gaps break it silently, and LAG over an explicit ordering is the honest version. Three-way self-joins are the shape behind "the same value three times in a row".

When it is the answer
  • A row is compared against another row of the same table: employee to manager, today to yesterday, seat to next seat.
  • The statement says "consecutive", "in a row", or "at least three times running".
  • A pair of rows is the answer: the two closest points, mutual follows, duplicated records.
  • The table encodes a hierarchy in one of its own columns.
Self-joins — the query
SELECT e.name AS employee, m.name AS manager
FROM   Employee AS e
JOIN   Employee AS m ON m.id = e.managerId   -- one table, two roles
WHERE  e.salary > m.salary;

Practise it on 180. Consecutive Numbers, 181. Employees Earning More Than Their Managers, 196. Delete Duplicate Emails and 5 more below.

Window functions: RANK, DENSE_RANK and ROW_NUMBER

Rank, number or accumulate within a group without collapsing the rows.

A window function computes over a set of rows related to the current one and, unlike an aggregate, leaves the rows where they are. That is the entire difference: GROUP BY department gives you one row per department, while OVER (PARTITION BY department) gives you every row with its department's answer attached. The three ranking functions differ only in how they treat ties, and picking the wrong one is the most common wrong answer on this track — ROW_NUMBER gives 1, 2, 3, 4 and breaks ties arbitrarily; RANK gives 1, 2, 2, 4, skipping after a tie; DENSE_RANK gives 1, 2, 2, 3, which is what "the top three salaries, ties included" actually means. The mechanical rule to carry into the interview is that a window function cannot appear in WHERE or HAVING, because both are evaluated before the window is: the ranked query has to be wrapped in a subquery or a CTE and filtered from outside. SUM(...) OVER (PARTITION BY x ORDER BY d) is a running total, and LAG and LEAD reach the previous or next row directly, which beats a self-join on id whenever the ids might have gaps.

When it is the answer
  • Top N per group, where the treatment of ties is part of the question.
  • Every row needs its position within its own group attached to it.
  • A running total, a cumulative count, or a moving window over an ordering.
  • The previous or the next row's value is needed — LAG and LEAD rather than an arithmetic self-join.
Window functions: RANK, DENSE_RANK and ROW_NUMBER — the query
SELECT department, name, salary
FROM (
  SELECT department, name, salary,
         DENSE_RANK() OVER (PARTITION BY department
                            ORDER BY salary DESC) AS place
  FROM   Employee
) AS ranked
WHERE  place <= 3;   -- filtered outside: WHERE is evaluated before the window

Practise it on 177. Nth Highest Salary, 178. Rank Scores, 185. Department Top Three Salaries and 1 more below.

Correlated subqueries

A subquery that mentions the outer row, and therefore runs once per outer row.

An ordinary subquery is evaluated once and its result substituted in. A correlated one refers to a column of the query around it, so it is conceptually re-evaluated for every outer row — and that is what lets it express "…than any other row in its own group". Written out, it reads almost exactly like the sentence in the problem statement, and it keeps ties, which an ORDER BY with LIMIT 1 silently discards. EXISTS is the same construction with the result thrown away: it stops at the first matching row, so it is the right form when the question is only whether something exists, and NOT EXISTS is the anti-join that keeps working when the inner column is nullable, which NOT IN does not. The cost is real, because the inner query runs per row rather than once, so the window-function form of the same question is usually the faster one — both are accepted, and the correlated version is usually the one you can write correctly first.

When it is the answer
  • The maximum or minimum within each group, with ties kept.
  • A row is compared against an aggregate of the rows around it.
  • The question is about existence rather than about a value — EXISTS and NOT EXISTS.
  • The statement can be read out loud as "…where there is no other row such that…".
Correlated subqueries — the query
SELECT e.name, e.salary
FROM   Employee AS e
WHERE  e.salary = (SELECT MAX(x.salary)
                   FROM   Employee AS x
                   WHERE  x.department = e.department);   -- re-runs per outer row

Practise it on 184. Department Highest Salary, 512. Game Play Analysis II.

Date arithmetic

Compare, bucket and difference dates as dates, not as the strings they print as.

A date is its own type, and the first rule is not to compare it as text: '2024-9-1' and '2024-09-01' are the same day and different strings. Adding an interval to a column is how "the day after" is expressed, and joining on that expression is how every consecutive-day problem is written. This is the one place the dialects visibly diverge — MySQL writes d + INTERVAL 1 DAY, PostgreSQL writes d + INTERVAL '1 day', Oracle writes d + 1 — while everything else on this page is the same in all of them. Keep the arithmetic on the constant side of a comparison wherever you can: a half-open range over the raw column can use an index and a function wrapped around the column cannot, and the wrapped form also changes the type on one side of the comparison. Grouping by month means truncating the date to the month and grouping on the truncated value, and a "within the last 30 days" filter is half-open for the same reason a month bucket is — the closed form counts the boundary day twice.

When it is the answer
  • Consecutive days, "the next day", "the day before".
  • Rows are bucketed by month, quarter or year.
  • A rolling window: the last seven days, the trailing three months.
  • The gap between two timestamps is either the answer or the filter.
Date arithmetic — the query
SELECT today.id
FROM   Weather AS yesterday
JOIN   Weather AS today
  ON   today.recordDate = yesterday.recordDate + INTERVAL 1 DAY
WHERE  today.temperature > yesterday.temperature;

Practise it on 197. Rising Temperature, 550. Game Play Analysis IV, 615. Average Salary: Departments VS Company.

NULL handling

NULL means unknown — not zero, not empty — and most wrong answers on this track are made of it.

Every comparison against NULL evaluates to unknown, and a WHERE clause keeps only the rows that evaluate to true, so referee_id <> 2 throws away every row whose referee_id is NULL instead of keeping it. Those rows have to be asked for explicitly with IS NULL, or given a stand-in value with COALESCE. The same rule wrecks NOT IN: if the subquery returns even a single NULL, then x NOT IN (…) is unknown for every x and the query returns nothing at all — which is why the anti-join, a LEFT JOIN with an IS NULL check on the right-hand side, is the safe way to write "customers who never ordered". The aggregate side has the mirror image of the problem: SUM and AVG ignore NULLs entirely, so an average over a column of NULLs is NULL rather than zero, and COUNT(column) skips them while COUNT(*) does not. On the outer side of a LEFT JOIN that difference is the answer: COUNT(right.id) counts real children and COUNT(*) counts one for a parent that has none.

When it is the answer
  • The words "never", "no matching", or "has not yet" appear — that is an anti-join.
  • Rows have to survive a join that found nothing to match them with.
  • A nullable column is being filtered with <> or NOT IN.
  • Something is counted or averaged over a column that is allowed to be empty.
NULL handling — the query
-- a comparison never matches NULL, so those rows must be asked for
SELECT name FROM Customer WHERE referee_id <> 2 OR referee_id IS NULL;

-- an anti-join: keep only the rows the LEFT JOIN found no partner for
SELECT c.name
FROM   Customers AS c
LEFT JOIN Orders AS o ON o.customerId = c.id
WHERE  o.id IS NULL;

Practise it on 175. Combine Two Tables, 183. Customers Who Never Order, 577. Employee Bonus and 3 more below.

Pivoting with CASE

Turn rows into columns, and conditions into numbers, by putting CASE inside an aggregate.

CASE is an expression, so it can go anywhere a column can — including inside an aggregate, which is where it stops being a formatting device and becomes a technique. SUM(CASE WHEN cond THEN 1 ELSE 0 END) counts the rows in a group that satisfy a condition, and dividing that by COUNT(*) gives the group's rate, which ROUND then trims to whatever precision the problem asked for. MAX(CASE WHEN key = 'x' THEN value END) moves one value per key into a column of its own, which is the pivot from tall to wide. The asymmetry between those two is the thing to remember: use ELSE 0 when you are counting, and omit ELSE entirely when you are pivoting, because a zero would compete with the real value inside the MAX while a NULL is ignored by it. The same expression covers the problems that ask for a computed label rather than a stored one, and inside an UPDATE it is how a column is rewritten in both directions at once — something no pair of sequential UPDATE statements can do without a temporary value.

When it is the answer
  • A rate, a percentage, or "how many of these are that" per group.
  • One column of keys has to become several columns of values.
  • The output is a label chosen by a condition rather than a value read from a row.
  • Two values have to be swapped in place in a single statement.
Pivoting with CASE — the query
SELECT   student,
         MAX(CASE WHEN subject = 'Maths'   THEN score END) AS maths,    -- no ELSE
         MAX(CASE WHEN subject = 'Physics' THEN score END) AS physics,
         ROUND(SUM(CASE WHEN score < 50 THEN 1 ELSE 0 END)
               / COUNT(*), 2)                                AS fail_rate
FROM     Marks
GROUP BY student;

Practise it on 262. Trips and Users, 578. Get Highest Answer Rate Question, 608. Tree Node and 4 more below.

Every Database problem numbered 750 or below whose page here carries the question restated in plain English, a worked example with real rows, and a working solution. Each row is labelled with the query shape it drills, so the table doubles as a syllabus: take a shape, do its problems, move on. Free problems come first and the LeetCode Premium ones after them, each in ascending problem-number order.

#ProblemDifficultyQuery shape
175Combine Two TablesEasyNULL handling
176Second Highest SalaryMediumFiltering and ordering one table
177Nth Highest SalaryMediumWindow functions: RANK, DENSE_RANK and ROW_NUMBER
178Rank ScoresMediumWindow functions: RANK, DENSE_RANK and ROW_NUMBER
180Consecutive NumbersMediumSelf-joins
181Employees Earning More Than Their ManagersEasySelf-joins
182Duplicate EmailsEasyAggregation with GROUP BY and HAVING
183Customers Who Never OrderEasyNULL handling
184Department Highest SalaryMediumCorrelated subqueries
185Department Top Three SalariesHardWindow functions: RANK, DENSE_RANK and ROW_NUMBER
196Delete Duplicate EmailsEasySelf-joins
197Rising TemperatureEasyDate arithmetic
262Trips and UsersHardPivoting with CASE
511Game Play Analysis IEasyAggregation with GROUP BY and HAVING
550Game Play Analysis IVMediumDate arithmetic
570Managers with at Least 5 Direct ReportsMediumAggregation with GROUP BY and HAVING
577Employee BonusEasyNULL handling
584Find Customer RefereeEasyNULL handling
585Investments in 2016MediumAggregation with GROUP BY and HAVING
586Customer Placing the Largest Number of OrdersEasyAggregation with GROUP BY and HAVING
595Big CountriesEasyFiltering and ordering one table
596Classes With at Least 5 StudentsEasyAggregation with GROUP BY and HAVING
601Human Traffic of StadiumHardSelf-joins
602Friend Requests II: Who Has the Most FriendsMediumAggregation with GROUP BY and HAVING
607Sales PersonEasyNULL handling
608Tree NodeMediumPivoting with CASE
610Triangle JudgementEasyPivoting with CASE
619Biggest Single NumberEasyAggregation with GROUP BY and HAVING
620Not Boring MoviesEasyFiltering and ordering one table
626Exchange SeatsMediumPivoting with CASE
627Swap Sex of EmployeesEasyPivoting with CASE
512Game Play Analysis IIPremiumEasyCorrelated subqueries
534Game Play Analysis IIIPremiumMediumWindow functions: RANK, DENSE_RANK and ROW_NUMBER
574Winning CandidatePremiumMediumAggregation with GROUP BY and HAVING
578Get Highest Answer Rate QuestionPremiumMediumPivoting with CASE
580Count Student Number in DepartmentsPremiumMediumNULL handling
597Friend Requests I: Overall Acceptance RatePremiumEasyAggregation with GROUP BY and HAVING
603Consecutive Available SeatsPremiumEasySelf-joins
612Shortest Distance in a PlanePremiumMediumSelf-joins
613Shortest Distance in a LinePremiumEasySelf-joins
614Second Degree FollowerPremiumMediumSelf-joins
615Average Salary: Departments VS CompanyPremiumHardDate arithmetic
618Students Report By GeographyPremiumHardPivoting with CASE

All 249 LeetCode SQL problems by difficulty

Every problem in the library that LeetCode tags Database, grouped by LeetCode's own difficulty rating. 33 of the 249 carry a complete solution with a worked example; the rest are listed for completeness, with the LeetCode Premium ones marked — a Premium problem's statement is paywalled on LeetCode itself, so there is only so much any page can say about it.

Easy (100)

#ProblemDifficultyTopics
175Combine Two TablesEasyDatabase
181Employees Earning More Than Their ManagersEasyDatabase
182Duplicate EmailsEasyDatabase
183Customers Who Never OrderEasyDatabase
196Delete Duplicate EmailsEasyDatabase
197Rising TemperatureEasyDatabase
511Game Play Analysis IEasyDatabase
577Employee BonusEasyDatabase
584Find Customer RefereeEasyDatabase
586Customer Placing the Largest Number of OrdersEasyDatabase
595Big CountriesEasyDatabase
596Classes With at Least 5 StudentsEasyDatabase
607Sales PersonEasyDatabase
610Triangle JudgementEasyDatabase
619Biggest Single NumberEasyDatabase
620Not Boring MoviesEasyDatabase
627Swap Sex of EmployeesEasyDatabase
1050Actors and Directors Who Cooperated At Least Three TimesEasyDatabase
1068Product Sales Analysis IEasyDatabase
512Game Play Analysis IIPremiumEasyDatabase
597Friend Requests I: Overall Acceptance RatePremiumEasyDatabase
603Consecutive Available SeatsPremiumEasyDatabase
613Shortest Distance in a LinePremiumEasyDatabase
1069Product Sales Analysis IIPremiumEasyDatabase
1075Project Employees IEasyDatabase
1076Project Employees IIPremiumEasyDatabase
1082Sales Analysis IPremiumEasyDatabase
1083Sales Analysis IIPremiumEasyDatabase
1084Sales Analysis IIIEasyDatabase
1113Reported PostsPremiumEasyDatabase
1141User Activity for the Past 30 Days IEasyDatabase
1142User Activity for the Past 30 Days IIPremiumEasyDatabase
1148Article Views IEasyDatabase
1173Immediate Food Delivery IPremiumEasyDatabase
1179Reformat Department TableEasyDatabase
1211Queries Quality and PercentageEasyDatabase
1241Number of Comments per PostPremiumEasyDatabase
1251Average Selling PriceEasyDatabase
1280Students and ExaminationsEasyDatabase
1294Weather Type in Each CountryPremiumEasyDatabase
1303Find the Team SizePremiumEasyDatabase
1322Ads PerformancePremiumEasyDatabase
1327List the Products Ordered in a PeriodEasyDatabase
1350Students With Invalid DepartmentsPremiumEasyDatabase
1378Replace Employee ID With The Unique IdentifierEasyDatabase
1407Top TravellersEasyDatabase
1421NPV QueriesPremiumEasyDatabase
1435Create a Session Bar ChartPremiumEasyDatabase
1484Group Sold Products By The DateEasyDatabase
1495Friendly Movies Streamed Last MonthPremiumEasyDatabase
1511Customer Order FrequencyPremiumEasyDatabase
1517Find Users With Valid E-MailsEasyDatabase
1527Patients With a ConditionEasyDatabase
1543Fix Product Name FormatPremiumEasyDatabase
1565Unique Orders and Customers Per MonthPremiumEasyDatabase
1571Warehouse ManagerPremiumEasyDatabase
1581Customer Who Visited but Did Not Make Any TransactionsEasyDatabase
1587Bank Account Summary IIEasyDatabase
1607Sellers With No SalesPremiumEasyDatabase
1623All Valid Triplets That Can Represent a CountryPremiumEasyDatabase
1633Percentage of Users Attended a ContestEasyDatabase
1661Average Time of Process per MachineEasyDatabase
1667Fix Names in a TableEasyDatabase
1677Product's Worth Over InvoicesPremiumEasyDatabase
1683Invalid TweetsEasyDatabase
1693Daily Leads and PartnersEasyDatabase
1729Find Followers CountEasyDatabase
1731The Number of Employees Which Report to Each EmployeeEasyDatabase
1741Find Total Time Spent by Each EmployeeEasyDatabase
1757Recyclable and Low Fat ProductsEasyDatabase
1777Product's Price for Each StorePremiumEasyDatabase
1789Primary Department for Each EmployeeEasyDatabase
1795Rearrange Products TableEasyDatabase
1809Ad-Free SessionsPremiumEasyDatabase
1821Find Customers With Positive Revenue this YearPremiumEasyDatabase
1853Convert Date FormatPremiumEasyDatabase
1873Calculate Special BonusEasyDatabase
1890The Latest Login in 2020EasyDatabase
1939Users That Actively Request Confirmation MessagesPremiumEasyDatabase
1965Employees With Missing InformationEasyDatabase
1978Employees Whose Manager Left the CompanyEasyDatabase
2026Low-Quality ProblemsPremiumEasyDatabase
2072The Winner UniversityPremiumEasyDatabase
2082The Number of Rich CustomersPremiumEasyDatabase
2205The Number of Users That Are Eligible for DiscountPremiumEasyDatabase
2230The Users That Are Eligible for DiscountPremiumEasyDatabase
2329Product Sales Analysis VPremiumEasyDatabase
2339All the Matches of the LeaguePremiumEasyDatabase
2356Number of Unique Subjects Taught by Each TeacherEasyDatabase
2377Sort the Olympic TablePremiumEasyDatabase
2480Form a Chemical BondPremiumEasyDatabase
2504Concatenate the Name and the ProfessionPremiumEasyDatabase
2668Find Latest SalariesPremiumEasyDatabase
2669Count Artist Occurrences On Spotify Ranking ListPremiumEasyDatabase
2687Bikes Last Time UsedPremiumEasyDatabase
2837Total Traveled DistancePremiumEasyDatabase
2853Highest Salaries DifferencePremiumEasyDatabase
2985Calculate Compressed MeanPremiumEasyDatabase
2987Find Expensive CitiesPremiumEasyDatabase
2990Loan TypesPremiumEasyDatabase

Medium (105)

#ProblemDifficultyTopics
176Second Highest SalaryMediumDatabase
177Nth Highest SalaryMediumDatabase
178Rank ScoresMediumDatabase
180Consecutive NumbersMediumDatabase
184Department Highest SalaryMediumDatabase
550Game Play Analysis IVMediumDatabase
570Managers with at Least 5 Direct ReportsMediumDatabase
585Investments in 2016MediumDatabase
602Friend Requests II: Who Has the Most FriendsMediumDatabase
608Tree NodeMediumDatabase
626Exchange SeatsMediumDatabase
534Game Play Analysis IIIPremiumMediumDatabase
574Winning CandidatePremiumMediumDatabase
578Get Highest Answer Rate QuestionPremiumMediumDatabase
580Count Student Number in DepartmentsPremiumMediumDatabase
612Shortest Distance in a PlanePremiumMediumDatabase
614Second Degree FollowerPremiumMediumDatabase
1045Customers Who Bought All ProductsMediumDatabase
1070Product Sales Analysis IIIMediumDatabase
1077Project Employees IIIPremiumMediumDatabase
1098Unpopular BooksPremiumMediumDatabase
1107New Users Daily CountPremiumMediumDatabase
1112Highest Grade For Each StudentPremiumMediumDatabase
1126Active BusinessesPremiumMediumDatabase
1132Reported Posts IIPremiumMediumDatabase
1149Article Views IIPremiumMediumDatabase
1158Market Analysis IMediumDatabase
1164Product Price at a Given DateMediumDatabase
1174Immediate Food Delivery IIMediumDatabase
1193Monthly Transactions IMediumDatabase
1204Last Person to Fit in the BusMediumDatabase
1205Monthly Transactions IIPremiumMediumDatabase
1212Team Scores in Football TournamentPremiumMediumDatabase
1264Page RecommendationsPremiumMediumDatabase
1270All People Report to the Given ManagerPremiumMediumDatabase
1285Find the Start and End Number of Continuous RangesPremiumMediumDatabase
1308Running Total for Different GendersPremiumMediumDatabase
1321Restaurant GrowthMediumDatabase
1341Movie RatingMediumDatabase
1355Activity ParticipantsPremiumMediumDatabase
1364Number of Trusted Contacts of a CustomerPremiumMediumDatabase
1393Capital Gain/LossMediumDatabase
1398Customers Who Bought Products A and B but Not CPremiumMediumDatabase
1440Evaluate Boolean ExpressionPremiumMediumDatabase
1445Apples & OrangesPremiumMediumDatabase
1454Active UsersPremiumMediumDatabase
1459Rectangles AreaPremiumMediumDatabase
1468Calculate SalariesPremiumMediumDatabase
1501Countries You Can Safely Invest InPremiumMediumDatabase
1532The Most Recent Three OrdersPremiumMediumDatabase
1549The Most Recent Orders for Each ProductPremiumMediumDatabase
1555Bank Account SummaryPremiumMediumDatabase
1596The Most Frequently Ordered Products for Each CustomerPremiumMediumDatabase
1613Find the Missing IDsPremiumMediumDatabase
1699Number of Calls Between Two PersonsPremiumMediumDatabase
1709Biggest Window Between VisitsPremiumMediumDatabase
1715Count Apples and OrangesPremiumMediumDatabase
1747Leetflex Banned AccountsPremiumMediumDatabase
1783Grand Slam TitlesPremiumMediumDatabase
1811Find Interview CandidatesPremiumMediumDatabase
1831Maximum Transaction Each DayPremiumMediumDatabase
1841League StatisticsPremiumMediumDatabase
1843Suspicious Bank AccountsPremiumMediumDatabase
1867Orders With Maximum Quantity Above AveragePremiumMediumDatabase
1875Group Employees of the Same SalaryPremiumMediumDatabase
1907Count Salary CategoriesMediumDatabase
1934Confirmation RateMediumDatabase
1949Strong FriendshipPremiumMediumDatabase
1951All the Pairs With the Maximum Number of Common FollowersPremiumMediumDatabase
1988Find Cutoff Score for Each SchoolPremiumMediumDatabase
1990Count the Number of ExperimentsPremiumMediumDatabase
2020Number of Accounts That Did Not StreamPremiumMediumDatabase
2041Accepted Candidates From the InterviewsPremiumMediumDatabase
2051The Category of Each Member in the StorePremiumMediumDatabase
2066Account BalancePremiumMediumDatabase
2084Drop Type 1 Orders for Customers With Type 0 OrdersPremiumMediumDatabase
2112The Airport With the Most TrafficPremiumMediumDatabase
2142The Number of Passengers in Each Bus IPremiumMediumDatabase
2159Order Two Columns IndependentlyPremiumMediumDatabase
2175The Change in Global RankingsPremiumMediumDatabase
2228Users With Two Purchases Within Seven DaysPremiumMediumDatabase
2238Number of Times a Driver Was a PassengerPremiumMediumDatabase
2292Products With Three or More Orders in Two Consecutive YearsPremiumMediumDatabase
2298Tasks Count in the WeekendPremiumMediumDatabase
2308Arrange Table by GenderPremiumMediumDatabase
2314The First Day of the Maximum Recorded Degree in Each CityPremiumMediumDatabase
2324Product Sales Analysis IVPremiumMediumDatabase
2346Compute the Rank as a PercentagePremiumMediumDatabase
2372Calculate the Influence of Each SalespersonPremiumMediumDatabase
2388Change Null Values in a Table to the Previous ValuePremiumMediumDatabase
2394Employees With DeductionsPremiumMediumDatabase
2686Immediate Food Delivery IIIPremiumMediumDatabase
2688Find Active UsersPremiumMediumDatabase
2738Count Occurrences in TextPremiumMediumDatabase
2783Flight Occupancy and Waitlist AnalysisPremiumMediumDatabase
2820Election ResultsPremiumMediumDatabase
2854Rolling Average StepsPremiumMediumDatabase
2893Calculate Orders Within Each IntervalPremiumMediumDatabase
2922Market Analysis IIIPremiumMediumDatabase
2978Symmetric CoordinatesPremiumMediumDatabase
2984Find Peak Calling Hours for Each CityPremiumMediumDatabase
2986Find Third TransactionPremiumMediumDatabase
2988Manager of the Largest DepartmentPremiumMediumDatabase
2989Class PerformancePremiumMediumDatabase
2993Friday Purchases IPremiumMediumDatabase

Hard (44)

#ProblemDifficultyTopics
185Department Top Three SalariesHardDatabase
262Trips and UsersHardDatabase
601Human Traffic of StadiumHardDatabase
569Median Employee SalaryPremiumHardDatabase
571Find Median Given Frequency of NumbersPremiumHardDatabase
579Find Cumulative Salary of an EmployeePremiumHardDatabase
615Average Salary: Departments VS CompanyPremiumHardDatabase
618Students Report By GeographyPremiumHardDatabase
1097Game Play Analysis VPremiumHardDatabase
1127User Purchase PlatformPremiumHardDatabase
1159Market Analysis IIPremiumHardDatabase
1194Tournament WinnersPremiumHardDatabase
1225Report Contiguous DatesPremiumHardDatabase
1336Number of Transactions per VisitPremiumHardDatabase
1369Get the Second Most Recent ActivityPremiumHardDatabase
1384Total Sales Amount by YearPremiumHardDatabase
1412Find the Quiet Students in All ExamsPremiumHardDatabase
1479Sales by Day of the WeekPremiumHardDatabase
1635Hopper Company Queries IPremiumHardDatabase
1645Hopper Company Queries IIPremiumHardDatabase
1651Hopper Company Queries IIIPremiumHardDatabase
1767Find the Subtasks That Did Not ExecutePremiumHardDatabase
1892Page Recommendations IIPremiumHardDatabase
1917Leetcodify Friends RecommendationsPremiumHardDatabase
1919Leetcodify Similar FriendsPremiumHardDatabase
1972First and Last Call On the Same DayPremiumHardDatabase
2004The Number of Seniors and Juniors to Join the CompanyPremiumHardDatabase
2010The Number of Seniors and Juniors to Join the Company IIPremiumHardDatabase
2118Build the EquationPremiumHardDatabase
2153The Number of Passengers in Each Bus IIPremiumHardDatabase
2173Longest Winning StreakPremiumHardDatabase
2199Finding the Topic of Each PostPremiumHardDatabase
2252Dynamic Pivoting of a TablePremiumHardDatabase
2253Dynamic Unpivoting of a TablePremiumHardDatabase
2362Generate the InvoicePremiumHardDatabase
2474Customers With Strictly Increasing PurchasesPremiumHardDatabase
2494Merge Overlapping Events in the Same HallPremiumHardDatabase
2701Consecutive Transactions with Increasing AmountsPremiumHardDatabase
2720Popularity PercentagePremiumHardDatabase
2752Customers with Maximum Number of Transactions on Consecutive DaysPremiumHardDatabase
2793Status of Flight TicketsPremiumHardDatabase
2991Top Three WineriesPremiumHardDatabase
2994Friday Purchases IIPremiumHardDatabase
2995Viewers Turned StreamersPremiumHardDatabase

The pandas versions of the same questions

LeetCode also publishes 15 problems tagged Pandas, which put the same kind of relational question to a DataFrame instead of a table — a merge where this page has a join, a groupby where it has a GROUP BY. They are counted and listed separately because LeetCode publishes them as separate problems, and because the syntax you are being tested on is different even when the shape is not.

All 15 Pandas problems

LeetCode SQL FAQ

How many LeetCode SQL problems are there?

This library carries 249 problems that LeetCode tags Database — 100 Easy, 105 Medium and 44 Hard — plus 15 more that ask similar questions of a pandas DataFrame instead of a table.

Which LeetCode SQL problems should I do first?

Start with the 43 problems numbered 750 and below, listed on this page with the query shape each one drills. They are the lowest-numbered problems on the track and between them they cover 8 of the 8 query shapes, so one pass through that table means meeting each of those shapes in a real problem rather than only in a snippet.

What is the difference between WHERE and HAVING?

WHERE filters rows before they are grouped; HAVING filters the resulting groups afterwards. A condition on a column is therefore a WHERE, and a condition on a COUNT, SUM or AVG is a HAVING. Both belong in the same query more often than not, because filtering the rows first leaves fewer of them to group.

Do I need window functions to solve LeetCode SQL problems?

Not for most of them, but the ranking problems are much shorter with one. ROW_NUMBER, RANK and DENSE_RANK differ only in how they treat ties — 1, 2, 3, 4 against 1, 2, 2, 4 against 1, 2, 2, 3 — and choosing the wrong one is the most common wrong answer on this track. A window function cannot be used in WHERE or HAVING, so the ranked query has to be wrapped in a subquery or a CTE and filtered from outside.

Why does my NOT IN subquery return no rows?

Because the subquery returned a NULL. Every comparison against NULL evaluates to unknown, so x NOT IN (1, 2, NULL) is unknown for every x and the WHERE clause keeps nothing at all. Use a LEFT JOIN with an IS NULL check on the right-hand side, or NOT EXISTS, whenever the inner column is nullable.

Which SQL dialect are the queries on this page written in?

MySQL. Everything except the date arithmetic is standard SQL and runs unchanged elsewhere: MySQL writes d + INTERVAL 1 DAY, PostgreSQL writes d + INTERVAL '1 day' and Oracle writes d + 1. The query shapes themselves are identical in every dialect.

When the SQL screen is live and the schema is new

Stealth Interview is a desktop app for macOS and Windows. It reads the coding problem off your screen, returns a working solution with a step-by-step explanation and its time and space complexity, and transcribes what the interviewer is saying — while staying invisible to screen sharing.