SQL Practice Logo

SQLPractice Online

JOIN with Aggregation & GROUP BY: Examples

Module: Joins & Relationships

Basic JOIN with COUNT - Customer Order Counts

basic

Count orders per customer, including customers with zero orders

-- Wrong: INNER JOIN excludes customers without orders

SELECT c.customer_name, COUNT(o.order_id) as order_count

FROM customers c

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

GROUP BY c.customer_id, c.customer_name;

-- Result: Only customers with orders

-- Correct: LEFT JOIN includes all customers

SELECT c.customer_name, COUNT(o.order_id) as order_count

FROM customers c

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

GROUP BY c.customer_id, c.customer_name

ORDER BY order_count DESC;

Shows all customers with their order counts, including customers with 0 orders

LEFT JOIN preserves all customers. COUNT(o.order_id) ignores NULL values from customers without orders.

All

Multiple Aggregations with HAVING - Sales Analysis

intermediate

Calculate sales metrics by product category, filter for high-performing categories

-- Multiple aggregations with filtering

SELECT

cat.category_name,

COUNT(oi.order_item_id) as items_sold,

SUM(oi.quantity * oi.unit_price) as total_revenue,

AVG(oi.quantity * oi.unit_price) as avg_item_value,

COUNT(DISTINCT o.order_id) as unique_orders

FROM categories cat

LEFT JOIN products p ON cat.category_id = p.category_id

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

LEFT JOIN orders o ON oi.order_id = o.order_id

WHERE o.order_date >= '2024-01-01' OR o.order_date IS NULL

GROUP BY cat.category_id, cat.category_name

HAVING SUM(oi.quantity * oi.unit_price) > 10000 OR SUM(oi.quantity * oi.unit_price) IS NULL

ORDER BY total_revenue DESC NULLS LAST;

Shows category performance metrics for high-revenue categories and categories with no sales

Multiple LEFT JOINs with various aggregations. HAVING filters on aggregated values. NULL handling for categories without sales.

All

Complex Aggregation - Employee Performance Dashboard