067
LVL 03 — MID DEVELOPERSESSION 067DAY 67

SQL PART 2

🎫 PIXELCRAFT-054
Feature | 🟠 Hard | Priority: 🟠 High

Build the analytics dashboard backend. Complex queries: daily active users, filter popularity trends, storage usage per user, retention rates. Also: handle schema changes safely with migrations.
CONCEPTS.UNLOCKED
🔗
Foreign Keys & Relationships
One-to-many, many-to-many. A user has many events. An image has many tags. Foreign keys enforce referential integrity — can't reference a user that doesn't exist.
🪆
Subqueries
Queries within queries. "Find users whose upload count is above average" — the inner query calculates the average, the outer query filters by it.
📊
Window Functions
Running totals, rankings, moving averages. ROW_NUMBER(), RANK(), SUM() OVER(). Compute aggregates without collapsing rows — see both the detail and the summary.
🔄
Migrations
Evolving the database schema without losing data. ALTER TABLE adds columns safely. Migration files version your schema changes — like git for the database structure.
🧮
Aggregate Functions
COUNT, SUM, AVG, MIN, MAX. Answer questions about your data: total uploads, average file size, max storage used. Combine with GROUP BY for per-user or per-day breakdowns.
🔌
Express + PostgreSQL (pg)
const { Pool } = require('pg') — connect Express to PostgreSQL. Run SQL queries from your API routes. Build endpoints that power the analytics dashboard.
HANDS-ON.TASKS
01
Complex Analytics Queries
-- Daily active users (last 30 days) SELECT DATE(created_at) as day, COUNT(DISTINCT user_id) as active_users FROM analytics_events WHERE created_at > NOW() - INTERVAL '30 days' GROUP BY DATE(created_at) ORDER BY day; -- Most popular filters this week SELECT metadata->>'filter_name' as filter, COUNT(*) as uses FROM analytics_events WHERE event_type = 'filter_apply' AND created_at > NOW() - INTERVAL '7 days' GROUP BY filter ORDER BY uses DESC LIMIT 10; -- Storage usage per user SELECT u.name, COUNT(e.id) as image_count, ROUND(SUM( (e.metadata->>'size_mb')::numeric ), 2) as total_mb FROM users u JOIN analytics_events e ON u.id = e.user_id WHERE e.event_type = 'upload' GROUP BY u.name ORDER BY total_mb DESC;
02
Migrations
-- Migration: 001_add_avatar_to_users.sql ALTER TABLE users ADD COLUMN avatar_url TEXT; ALTER TABLE users ADD COLUMN last_login_at TIMESTAMP;
Migrations are versioned, ordered files that evolve your schema. Run them in sequence: 001, 002, 003. Rollback reverses them. Like git commits for your database structure.
03
Connect Express to PostgreSQL
const { Pool } = require('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); app.get('/api/analytics/daily-active-users', authenticate, async (req, res) => { const result = await pool.query(` SELECT DATE(created_at) as day, COUNT(DISTINCT user_id) as active_users FROM analytics_events WHERE created_at > NOW() - INTERVAL '30 days' GROUP BY DATE(created_at) ORDER BY day `); res.json(result.rows); });
04
Build Analytics Dashboard in React

Build an analytics dashboard page showing charts of usage data: daily active users line chart, filter popularity bar chart, storage usage per user table.

05
Close the Ticket
git switch -c feature/PIXELCRAFT-054-analytics-dashboard git add server/ src/ git commit -m "Add analytics dashboard with complex SQL queries (PIXELCRAFT-054)" git push origin feature/PIXELCRAFT-054-analytics-dashboard # PR → Review → Merge → Close ticket ✅
CS.DEEP-DIVE

Database normalization.

Every database design is a tradeoff between: read speed, write speed, data consistency, and storage efficiency.

// Normalization vs Denormalization:

Normalized (split into tables)
  Update name once → correct
  everywhere. But: queries need JOINs

Denormalized (duplicate data)
  Faster reads. But: harder to keep
  consistent across copies

// Relational DBs favor normalization.
// Document DBs favor denormalization.
// Choose based on your access patterns.
"Analytics Lab"
[A]Add window functions: "rank users by total uploads" with RANK(), "running total of uploads per day" with SUM() OVER (ORDER BY day). Show rankings in the dashboard.
[B]Add retention analysis: "what percentage of users who signed up in week 1 are still active in week 4?" This is a cohort analysis — one of the most important product metrics.
[C]Research an ORM for PostgreSQL: Prisma or Knex.js. Build the same analytics queries using the ORM. Compare: SQL readability vs ORM abstraction, migration tools, type safety.
REF.MATERIAL
ARTICLE
PostgreSQL Team
Complete window function reference: ROW_NUMBER, RANK, SUM OVER, PARTITION BY. The advanced SQL features powering analytics.
WINDOWOFFICIALESSENTIAL
VIDEO
Fireship
Visual explanation of window functions: partitions, frames, ranking, and running totals with practical examples.
WINDOWVISUAL
ARTICLE
Brian Carlson
The pg library for Node.js: connection pools, parameterized queries, transactions, and streaming results.
PGNODE.JSOFFICIAL
ARTICLE
Wikipedia
Normal forms (1NF through 5NF), functional dependencies, and the theory behind splitting data into tables for consistency.
NORMALIZATIONTHEORYCS
VIDEO
Fireship
INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN visualized with Venn diagrams. The most shared SQL resource on the internet.
JOINSVISUAL
// LEAVE EXCITED BECAUSE
You wrote SQL queries that answer real business questions. The analytics dashboard shows user trends, popular features, and usage patterns. This is the data that drives product decisions at real companies.