SQL Boy
TutorialsPlayground

Format & Validate

SQL FormatterSQL MinifierSyntax Validator

Convert

JSON to SQLCSV to SQLSQL to JSONRegex to SQLExcel to SQLSQL Dialect Convertersoon

Visualize

ER Diagram GeneratorSQL Schema Diff

Generate

SQL Mock Data Generator

Analyze

SQL Query ExplainerSQL Query Analyzer

Workflow hubs

FormattingConversionSchemaAnalysis
View all tools
Daily ChallengeInterviewsCheat SheetBlog

© 2026 SQL Boy. Built for developers.

ContactPrivacyTermsAI Usage PolicyEditorial StandardsAboutRSS Feed

New conversation

What can I help with?

Ask about this page, get a hint on a challenge, or explore SQL concepts.

I know what's on this page and can give answers grounded in SQL Boy content.

Current page

Customers Who Bought All Products

/challenges/customers-who-bought-all-products

Usage status will load after login
SQL Boy
TutorialsPlayground

Format & Validate

SQL FormatterSQL MinifierSyntax Validator

Convert

JSON to SQLCSV to SQLSQL to JSONRegex to SQLExcel to SQLSQL Dialect Convertersoon

Visualize

ER Diagram GeneratorSQL Schema Diff

Generate

SQL Mock Data Generator

Analyze

SQL Query ExplainerSQL Query Analyzer

Workflow hubs

FormattingConversionSchemaAnalysis
View all tools
Daily ChallengeInterviewsCheat SheetBlog
SQL Challenges/Customers Who Bought All Products
Challenge DetailMediumReviewed 2026-04-20

Customers Who Bought All Products

Report the customer ids from the Customer table that bought all the products in the Product table.

SubqueriesAggregation

This challenge now meets the current minimum standard for sitemap inclusion and independent indexing.

2026-01-20Medium

Customers Who Bought All Products

Report the customer ids from the Customer table that bought all the products in the Product table.

Available Tables:
SQL Editor
Loading...

What This Challenge Is Testing

This is a compact example of relational division: finding entities that are related to every value in another set. The same idea appears in entitlement checks, feature adoption queries, and completeness reporting where a user must satisfy all required items.

Topic Tags

SubqueriesAggregationAnalytics

Schema At A Glance

customer
customer_idproduct_key
product
product_key

Solution Approaches

01

Count distinct purchased products per customer

SELECT
  customer_id
FROM customer
GROUP BY customer_id
HAVING COUNT(DISTINCT product_key) = (
  SELECT COUNT(*)
  FROM product
)

The product table defines the full required set. If a customer has purchased the same number of distinct product keys as the catalog contains, then that customer has bought every product. This is the cleanest and most portable version for this schema.

02

Anti-join with NOT EXISTS

SELECT DISTINCT c.customer_id
FROM customer c
WHERE NOT EXISTS (
  SELECT 1
  FROM product p
  WHERE NOT EXISTS (
    SELECT 1
    FROM customer c2
    WHERE c2.customer_id = c.customer_id
      AND c2.product_key = p.product_key
  )
)

The NOT EXISTS version expresses the logic more literally: there must not exist any product that the current customer failed to buy. It is more verbose than the counting approach, but it generalizes well when duplicates or extra conditions make direct counts less obvious.

Common Pitfalls

Do not use COUNT(product_key) without DISTINCT if duplicate purchases are possible. A customer who bought the same product multiple times could then appear to cover the entire catalog even when they are missing another product.

Frequently Asked Questions

Why compare against the product table instead of a hard-coded number?

The product table is the authoritative definition of the full set. Hard-coding the required count makes the query brittle when the catalog changes.

When is NOT EXISTS better than the COUNT approach?

NOT EXISTS is useful when the matching rules become more complex than a simple distinct count, or when you want the logic to read as an explicit all-items check instead of a counting shortcut.

Concept Guides

Use these guides when you want the fuller explanation behind the SQL pattern this challenge is testing.

SQL Subqueries Explained: Queries Within Queries

Unlock the power of nested queries. Learn when to use subqueries in SELECT, WHERE, and FROM clauses with practical, runnable examples.

Mastering SQL Set Operations: UNION, INTERSECT, and EXCEPT

Learn how to combine datasets using SQL set operations. We focus on INTERSECT, EXCEPT, and the nuances of combining result sets.

SQL EXISTS vs IN: When to Use Each (With Performance Tips)

Understand the difference between EXISTS and IN in SQL. Learn which performs better and avoid the NOT IN NULL trap.

Topic Hubs

If this problem exposed a deeper weakness, use a topic hub to move through a curated cluster instead of random article hopping.

Advanced SQL

Advanced query patterns

Use this path when you are moving beyond beginner SELECT queries into CTEs, window functions, and conditional logic.

Practice Path

If you want the rotating practice flow, open this same question from the daily stream. If you want interview-style packaging, continue into the interview pool after this rep.

Back to ChallengesOpen In DailyBrowse Interviews

Related Challenges

Second Highest SalaryMedium

Find the second distinct highest salary without accidentally returning the same maximum twice.

Trips and UsersHard

Compute daily cancellation rate after excluding any trip where either the client or driver is banned.

Friend Requests I: Overall Acceptance RateMedium

Calculate overall friend request acceptance rate while separating request volume from accepted pairs cleanly.

© 2026 SQL Boy. Built for developers.

ContactPrivacyTermsAI Usage PolicyEditorial StandardsAboutRSS Feed