SQL Practice Logo

SQLPractice Online

ANTI-JOINs & Finding Non-Matching Rows: Examples

Module: Joins & Relationships

Basic Anti-Join - Customers Without Orders

basic

Find customers who have never placed an order for marketing campaigns

-- Anti-join pattern: LEFT JOIN + WHERE IS NULL

SELECT c.customer_id, c.customer_name, c.email, c.registration_date

FROM customers c

LEFT JOIN orders o ON c.customer_id = o.customer_id

WHERE o.customer_id IS NULL -- Check right table PRIMARY KEY

ORDER BY c.registration_date DESC;

-- Alternative: NOT EXISTS (often faster)

SELECT c.customer_id, c.customer_name, c.email, c.registration_date

FROM customers c

WHERE NOT EXISTS (

SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id

)

ORDER BY c.registration_date DESC;

Returns customers who have never placed orders

LEFT JOIN preserves all customers. WHERE o.customer_id IS NULL finds customers without matches in orders table.

All

Products Never Sold - Inventory Analysis

intermediate

Find products that have never been ordered for clearance or discontinuation

-- Find unsold products with additional context

SELECT

p.product_id,

p.product_name,

p.category,

p.price,

p.stock_quantity,

p.created_date,

DATEDIFF(CURRENT_DATE, p.created_date) as days_in_catalog

FROM products p

LEFT JOIN order_items oi ON p.product_id = oi.product_id

WHERE oi.product_id IS NULL -- No sales records

AND p.status = 'active'

AND p.created_date < CURRENT_DATE - INTERVAL 30 DAY -- At least 30 days old

ORDER BY p.created_date ASC;

Shows products never sold with context like stock levels and time in catalog

Anti-join finds products without order_items records. Additional filters for active products older than 30 days.

All