DEV Community

Cover image for Building Two SQL Dashboards: E-commerce Analytics + Student Performance Reporting
Sourav Sarkar
Sourav Sarkar

Posted on

Building Two SQL Dashboards: E-commerce Analytics + Student Performance Reporting

Over the past week, I worked on two hands-on SQL projects as part of my learning journey. Both projects strengthened my analytical skills and helped me understand how SQL powers real-world decision-making.

This blog covers:

E-commerce Analytics Dashboard (revenue, top products, customer behavior)

Student Management Dashboard (averages, top scorers, subject difficulty)

I’m sharing my queries, approach, and key findings so others learning SQL can see how business insights come together using joins, aggregations, window functions, and time-series logic.

πŸ›’ Project 1: E-commerce Analytics Dashboard (SQL)

The goal was to understand customer behavior, product performance, and revenue trends using an e-commerce dataset consisting of:

  • customers
  • products
  • orders
  • order_items

Below are the insights I generated.

πŸ“ˆ 1. Monthly Revenue Trend (Last 24 Months)

I used DATE_TRUNC() to group sales by month and track revenue over the last two years.

SELECT
    TO_CHAR(DATE_TRUNC('month', o.order_date), 'Month YYYY') AS month_label,
    DATE_TRUNC('month', o.order_date) AS month_start,
    SUM(oi.quantity * oi.unit_price) AS total_revenue,
    COUNT(*) AS total_orders
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.order_date >= NOW() - INTERVAL '24 months'
GROUP BY month_start
ORDER BY month_start;

Enter fullscreen mode Exit fullscreen mode

πŸ” What it tells us

  1. Month-over-month revenue changes
  2. Growth direction for the business

πŸ“Έ Screenshot :

πŸ”„ 2. Customers Whose Orders Increased from 2024 β†’ 2025

This query compares order counts across years to identify fast-growing customers.

select 
c.name,c.customer_id,
sum(case when extract(year from o.order_date) = 2025 then 1 else 0 end) as year_date_2025,
sum(case when extract(year from o.order_date) = 2024 then 1 else 0 end) as year_date_2024
from customers as c
join orders as o on o.customer_id  = c.customer_id
group by c.name,c.customer_id
having 
      sum(case when extract(year from o.order_date) = 2025 then 1 end)
    > sum(case when extract(year from o.order_date) = 2024 then 1 end)
   AND 
      sum(case when extract(year from o.order_date) = 2025 then 1 end) > 0
   AND
      sum(case when extract(year from o.order_date) = 2024 then 1 end) > 0;
Enter fullscreen mode Exit fullscreen mode

πŸ” What it tells us

  • Which customers have become more active
  • A simple year-over-year loyalty signal
  • Helps identify customers worth targeting for retention campaigns

πŸ“Έ Screenshot:

πŸ† 3. Top 3 Products in Each Category (Window Function)

Using ROW_NUMBER() to rank items within each category:

select * from (
    select 
        p.name as product_name, 
        p.category,
        p.product_id,
        sum(ot.quantity * ot.unit_price) as total_sales,
        row_number() over(
            partition by p.category
            order by sum(ot.quantity * ot.unit_price) desc
        ) as rn
    from products as p
    join order_items as ot on ot.product_id = p.product_id
    group by p.category,p.name,p.product_id
) x 
where rn <= 3
order by category, total_sales desc;
Enter fullscreen mode Exit fullscreen mode

πŸ” What it tells us

  • The top performers inside each category
  • Helps identify products to promote or bundle

πŸ“Έ Screenshot:

πŸ›οΈ 4. Top 10 Best-Selling Products (By Quantity)

select 
products.product_id,
products.name as product_name,
sum(order_items.unit_price * order_items.quantity) as total_sale,
sum(order_items.quantity) as quantity
from products
join order_items on order_items.product_id = products.product_id
group by products.product_id
order by total_sale desc
limit 10;
Enter fullscreen mode Exit fullscreen mode

πŸ” Key insight

  • 1. These are your highest-demand products
  • 2. Useful for stock planning and reorder frequency

πŸ’° 5. Top 15 Revenue Generating Products

select 
products.product_id as product_id,
products.name as product_name,
sum(order_items.quantity) as total_units_sold,
round(avg(order_items.unit_price),2) as avg_unit_price,
sum(order_items.quantity * order_items.unit_price) as total_revenue
from products
join order_items on order_items.product_id = products.product_id
group by products.product_id
order by total_revenue desc
limit 15;
Enter fullscreen mode Exit fullscreen mode

πŸ” Key insight

  • These products make the biggest contribution to revenue

πŸ“Έ Screenshot :

🧩 Other Insights (from my additional queries)

  • Average Order Value per month β†’ financial health indicator
  • Category performance β†’ which category earns the most
  • One-time vs repeat customers β†’ customer segmentation
  • Top spenders β†’ lifetime value leaderboard

Together, these form a complete e-commerce analytics dashboard using SQL.

πŸŽ“ Project 2: Student Management Dashboard (SQL)

This project focused on analyzing academic performance using tables:

  1. students
  2. subjects
  3. scores

The goal was to create insights similar to what a school dashboard would show.

πŸ“Š 1. Student Performance Summary

Using AVG, MIN, MAX, and a CASE statement to create a β€œperformance review”.

select 
s.name ,
round(avg(sc.score),2) as avg_score,
min(sc.score) as min_score,
max(sc.score) as max_score,
case 
   when round(avg(sc.score),2) > 95 then 'Academically Blessed'
   when round(avg(sc.score),2) > 90 then 'Top Performer'
   when round(avg(sc.score),2) > 80 then 'Above Average'
   when round(avg(sc.score),2) > 70 then 'Average'
   when round(avg(sc.score),2) > 55 then 'Needs Improvement'
   else 'Failing'
end as performance_review
from scores as sc
join students as s on s.student_id = sc.student_id
group by s.name;
Enter fullscreen mode Exit fullscreen mode

πŸ” What it tells us

  • Each student's average
  • Performance category
  • Range of scores

πŸ“Έ Screenshot:

πŸ… 2. Top Performers per Subject

SELECT 
    sub.subject_name,
    s.name AS top_student,
    sc.score AS top_score
FROM scores sc
JOIN subjects sub ON sub.subject_id = sc.subject_id
JOIN students s ON s.student_id = sc.student_id
WHERE sc.score = (
    SELECT MAX(score)
    FROM scores sc2
    WHERE sc2.subject_id = sc.subject_id
)
ORDER BY sub.subject_name;
Enter fullscreen mode Exit fullscreen mode

πŸ” Key insight

  • Highlights subject toppers

🎯 3. Subject Difficulty Overview

select sub.subject_name,
       round(avg(sc.score),2) as avg_mark,
       max(sc.score) as max_marks,
       min(sc.score) as min_marks,
       (sum(case when sc.score > 50 then 1 end) * 100 / count(*)) as passing_rate
from subjects as sub
join scores sc on sc.subject_id = sub.subject_id
group by sub.subject_name
order by passing_rate;
Enter fullscreen mode Exit fullscreen mode

πŸ” What it tells us

  • Which subjects are easiest/hardest
  • Passing rate trend
  • Score distribution visibility

πŸ“Έ Screenshot placeholder:

What I Learned from These Two Projects

  • Window functions (ROW_NUMBER)
  • Time-series analysis (DATE_TRUNC, TO_CHAR)
  • Business metrics like AOV, revenue, LTV
  • CASE expressions for segmentation
  • Joining multiple tables to build dashboards
  • Thinking like an analyst, not just writing queries

Both projects gave me real-world experience in building analytics dashboards purely using SQL.

Final Thoughts

These two projects helped me understand how SQL is used in:

  1. E-commerce analytics
  2. Education dashboards
  3. KPI tracking
  4. Ranking and segmentation
  5. Time-based reporting

If you're also learning SQL, try replicating these dashboards on any dataset you can find β€” it’s a great way to level up your analytical thinking. Feedbacks are appreciated

Data sets used

ecommerce

students

Top comments (0)