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.

Easy
100
Medium
105
Hard
44

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. 01Filtering and ordering one table
  2. 02Aggregation with GROUP BY and HAVING
  3. 03Self-joins
  4. 04Window functions: RANK, DENSE_RANK and ROW_NUMBER
  5. 05Correlated subqueries
  6. 06Date arithmetic
  7. 07NULL handling
  8. 08Pivoting 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.
SQLFiltering 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.
SQLAggregation 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.
SQLSelf-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.
SQLWindow 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…".
SQLCorrelated 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.
SQLDate 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.
SQLNULL 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.
SQLPivoting 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.

Eyes only

When the SQL screen is live and the schema is new.

In the live round, Stealth Interview reads the 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 says. It's a desktop app for macOS and Windows, invisible to screen sharing.

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)

Easy problems
No.Problem
0175Combine Two Tables
0181Employees Earning More Than Their Managers
0182Duplicate Emails
0183Customers Who Never Order
0196Delete Duplicate Emails
0197Rising Temperature
0511Game Play Analysis I
0577Employee Bonus
0584Find Customer Referee
0586Customer Placing the Largest Number of Orders
0595Big Countries
0596Classes With at Least 5 Students
0607Sales Person
0610Triangle Judgement
0619Biggest Single Number
0620Not Boring Movies
0627Swap Sex of Employees
1050Actors and Directors Who Cooperated At Least Three Times
1068Product Sales Analysis I
0512Game Play Analysis IIPremium
0597Friend Requests I: Overall Acceptance RatePremium
0603Consecutive Available SeatsPremium
0613Shortest Distance in a LinePremium
1069Product Sales Analysis IIPremium
1075Project Employees I
1076Project Employees IIPremium
1082Sales Analysis IPremium
1083Sales Analysis IIPremium
1084Sales Analysis III
1113Reported PostsPremium
1141User Activity for the Past 30 Days I
1142User Activity for the Past 30 Days IIPremium
1148Article Views I
1173Immediate Food Delivery IPremium
1179Reformat Department Table
1211Queries Quality and Percentage
1241Number of Comments per PostPremium
1251Average Selling Price
1280Students and Examinations
1294Weather Type in Each CountryPremium
1303Find the Team SizePremium
1322Ads PerformancePremium
1327List the Products Ordered in a Period
1350Students With Invalid DepartmentsPremium
1378Replace Employee ID With The Unique Identifier
1407Top Travellers
1421NPV QueriesPremium
1435Create a Session Bar ChartPremium
1484Group Sold Products By The Date
1495Friendly Movies Streamed Last MonthPremium
1511Customer Order FrequencyPremium
1517Find Users With Valid E-Mails
1527Patients With a Condition
1543Fix Product Name FormatPremium
1565Unique Orders and Customers Per MonthPremium
1571Warehouse ManagerPremium
1581Customer Who Visited but Did Not Make Any Transactions
1587Bank Account Summary II
1607Sellers With No SalesPremium
1623All Valid Triplets That Can Represent a CountryPremium
1633Percentage of Users Attended a Contest
1661Average Time of Process per Machine
1667Fix Names in a Table
1677Product's Worth Over InvoicesPremium
1683Invalid Tweets
1693Daily Leads and Partners
1729Find Followers Count
1731The Number of Employees Which Report to Each Employee
1741Find Total Time Spent by Each Employee
1757Recyclable and Low Fat Products
1777Product's Price for Each StorePremium
1789Primary Department for Each Employee
1795Rearrange Products Table
1809Ad-Free SessionsPremium
1821Find Customers With Positive Revenue this YearPremium
1853Convert Date FormatPremium
1873Calculate Special Bonus
1890The Latest Login in 2020
1939Users That Actively Request Confirmation MessagesPremium
1965Employees With Missing Information
1978Employees Whose Manager Left the Company
2026Low-Quality ProblemsPremium
2072The Winner UniversityPremium
2082The Number of Rich CustomersPremium
2205The Number of Users That Are Eligible for DiscountPremium
2230The Users That Are Eligible for DiscountPremium
2329Product Sales Analysis VPremium
2339All the Matches of the LeaguePremium
2356Number of Unique Subjects Taught by Each Teacher
2377Sort the Olympic TablePremium
2480Form a Chemical BondPremium
2504Concatenate the Name and the ProfessionPremium
2668Find Latest SalariesPremium
2669Count Artist Occurrences On Spotify Ranking ListPremium
2687Bikes Last Time UsedPremium
2837Total Traveled DistancePremium
2853Highest Salaries DifferencePremium
2985Calculate Compressed MeanPremium
2987Find Expensive CitiesPremium
2990Loan TypesPremium

Medium (105)

Medium problems
No.Problem
0176Second Highest Salary
0177Nth Highest Salary
0178Rank Scores
0180Consecutive Numbers
0184Department Highest Salary
0550Game Play Analysis IV
0570Managers with at Least 5 Direct Reports
0585Investments in 2016
0602Friend Requests II: Who Has the Most Friends
0608Tree Node
0626Exchange Seats
0534Game Play Analysis IIIPremium
0574Winning CandidatePremium
0578Get Highest Answer Rate QuestionPremium
0580Count Student Number in DepartmentsPremium
0612Shortest Distance in a PlanePremium
0614Second Degree FollowerPremium
1045Customers Who Bought All Products
1070Product Sales Analysis III
1077Project Employees IIIPremium
1098Unpopular BooksPremium
1107New Users Daily CountPremium
1112Highest Grade For Each StudentPremium
1126Active BusinessesPremium
1132Reported Posts IIPremium
1149Article Views IIPremium
1158Market Analysis I
1164Product Price at a Given Date
1174Immediate Food Delivery II
1193Monthly Transactions I
1204Last Person to Fit in the Bus
1205Monthly Transactions IIPremium
1212Team Scores in Football TournamentPremium
1264Page RecommendationsPremium
1270All People Report to the Given ManagerPremium
1285Find the Start and End Number of Continuous RangesPremium
1308Running Total for Different GendersPremium
1321Restaurant Growth
1341Movie Rating
1355Activity ParticipantsPremium
1364Number of Trusted Contacts of a CustomerPremium
1393Capital Gain/Loss
1398Customers Who Bought Products A and B but Not CPremium
1440Evaluate Boolean ExpressionPremium
1445Apples & OrangesPremium
1454Active UsersPremium
1459Rectangles AreaPremium
1468Calculate SalariesPremium
1501Countries You Can Safely Invest InPremium
1532The Most Recent Three OrdersPremium
1549The Most Recent Orders for Each ProductPremium
1555Bank Account SummaryPremium
1596The Most Frequently Ordered Products for Each CustomerPremium
1613Find the Missing IDsPremium
1699Number of Calls Between Two PersonsPremium
1709Biggest Window Between VisitsPremium
1715Count Apples and OrangesPremium
1747Leetflex Banned AccountsPremium
1783Grand Slam TitlesPremium
1811Find Interview CandidatesPremium
1831Maximum Transaction Each DayPremium
1841League StatisticsPremium
1843Suspicious Bank AccountsPremium
1867Orders With Maximum Quantity Above AveragePremium
1875Group Employees of the Same SalaryPremium
1907Count Salary Categories
1934Confirmation Rate
1949Strong FriendshipPremium
1951All the Pairs With the Maximum Number of Common FollowersPremium
1988Find Cutoff Score for Each SchoolPremium
1990Count the Number of ExperimentsPremium
2020Number of Accounts That Did Not StreamPremium
2041Accepted Candidates From the InterviewsPremium
2051The Category of Each Member in the StorePremium
2066Account BalancePremium
2084Drop Type 1 Orders for Customers With Type 0 OrdersPremium
2112The Airport With the Most TrafficPremium
2142The Number of Passengers in Each Bus IPremium
2159Order Two Columns IndependentlyPremium
2175The Change in Global RankingsPremium
2228Users With Two Purchases Within Seven DaysPremium
2238Number of Times a Driver Was a PassengerPremium
2292Products With Three or More Orders in Two Consecutive YearsPremium
2298Tasks Count in the WeekendPremium
2308Arrange Table by GenderPremium
2314The First Day of the Maximum Recorded Degree in Each CityPremium
2324Product Sales Analysis IVPremium
2346Compute the Rank as a PercentagePremium
2372Calculate the Influence of Each SalespersonPremium
2388Change Null Values in a Table to the Previous ValuePremium
2394Employees With DeductionsPremium
2686Immediate Food Delivery IIIPremium
2688Find Active UsersPremium
2738Count Occurrences in TextPremium
2783Flight Occupancy and Waitlist AnalysisPremium
2820Election ResultsPremium
2854Rolling Average StepsPremium
2893Calculate Orders Within Each IntervalPremium
2922Market Analysis IIIPremium
2978Symmetric CoordinatesPremium
2984Find Peak Calling Hours for Each CityPremium
2986Find Third TransactionPremium
2988Manager of the Largest DepartmentPremium
2989Class PerformancePremium
2993Friday Purchases IPremium

Hard (44)

Hard problems
No.Problem
0185Department Top Three Salaries
0262Trips and Users
0601Human Traffic of Stadium
0569Median Employee SalaryPremium
0571Find Median Given Frequency of NumbersPremium
0579Find Cumulative Salary of an EmployeePremium
0615Average Salary: Departments VS CompanyPremium
0618Students Report By GeographyPremium
1097Game Play Analysis VPremium
1127User Purchase PlatformPremium
1159Market Analysis IIPremium
1194Tournament WinnersPremium
1225Report Contiguous DatesPremium
1336Number of Transactions per VisitPremium
1369Get the Second Most Recent ActivityPremium
1384Total Sales Amount by YearPremium
1412Find the Quiet Students in All ExamsPremium
1479Sales by Day of the WeekPremium
1635Hopper Company Queries IPremium
1645Hopper Company Queries IIPremium
1651Hopper Company Queries IIIPremium
1767Find the Subtasks That Did Not ExecutePremium
1892Page Recommendations IIPremium
1917Leetcodify Friends RecommendationsPremium
1919Leetcodify Similar FriendsPremium
1972First and Last Call On the Same DayPremium
2004The Number of Seniors and Juniors to Join the CompanyPremium
2010The Number of Seniors and Juniors to Join the Company IIPremium
2118Build the EquationPremium
2153The Number of Passengers in Each Bus IIPremium
2173Longest Winning StreakPremium
2199Finding the Topic of Each PostPremium
2252Dynamic Pivoting of a TablePremium
2253Dynamic Unpivoting of a TablePremium
2362Generate the InvoicePremium
2474Customers With Strictly Increasing PurchasesPremium
2494Merge Overlapping Events in the Same HallPremium
2701Consecutive Transactions with Increasing AmountsPremium
2720Popularity PercentagePremium
2752Customers with Maximum Number of Transactions on Consecutive DaysPremium
2793Status of Flight TicketsPremium
2991Top Three WineriesPremium
2994Friday Purchases IIPremium
2995Viewers Turned StreamersPremium

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.