NM
Nabiya Maredia
Analytics Engineer in training → AI Analytics Engineer (target)
Baby due October 2026
3–4 hrs/day · 5 days/week
Target hire: Q2 2027
Last updated: August 2026
Modules Done
3 / 13
Current Phase
Pre-Baby Sprint
Weeks to Baby
10
Long-Term Target
AI Analytics Eng.
// overall_progress 23% complete
modules 01–03 committed · module 04 active · modules 05–13 planned
5-year career arc
🎯
Junior Data Analyst
2027
$55–75K
⚙️
Analytics Engineer
2027–2028
$90–130K
🔍
Senior AE · AI Focus
2028–2030
$130–180K
🧠
Staff AE · AI Data Lead
2030–2031
$180–260K
AI Analytics Engineer
2031+
$200–350K+
phase 1 — pre-baby sprint · now → october 2026
Active Complete SQL · Learn Tableau · Ship first portfolio project ~160 hrs total
01
SQL Fundamentals — SELECT, Filtering, Aggregations
The skeleton of every query you will ever write
✓ committed
⚡ Key mental model from this lesson
SQL has a strict execution order: WHERE filters rows first → GROUP BY buckets the survivors → HAVING filters the buckets → SELECT picks the columns → ORDER BY sorts → LIMIT cuts. Understanding this sequence prevents 80% of SQL mistakes.
SELECT · FROM · WHERE
The three-word skeleton of every SQL query. SELECT = what columns, FROM = which table, WHERE = which rows. The key insight: column names are structural references — they don't get quotes. Values like 'Open' do get quotes because they're actual data.
SELECT ticket_id, status FROM tickets WHERE status = 'Open'
AND · OR · != (compound filtering)
Chain multiple conditions together. AND = both must be true. OR = at least one must be true. != = not equal. Critical edge case learned: OR with two conditions covering all possible values always returns all rows — verified against TCS-style ticket data.
WHERE priority = 'High' AND status = 'Open'
COUNT · AVG · SUM (aggregations)
Summarise rows instead of retrieving them. COUNT(*) counts rows. AVG() averages a numeric column. NULL values are excluded from AVG automatically — NULL is not zero, it's the absence of a value, which breaks sorting and math differently.
SELECT AVG(resolution_hours) FROM tickets WHERE status = 'Closed'
GROUP BY · HAVING
GROUP BY splits your aggregation into buckets by category. HAVING then filters those buckets — you can't use WHERE to filter on aggregated results because WHERE runs before the groups exist. HAVING runs after grouping.
GROUP BY priority HAVING AVG(resolution_hours) > 5
ORDER BY · LIMIT
ORDER BY sorts results ASC (smallest first) or DESC (largest first). LIMIT caps the number of rows returned. Combined, they answer "top N" questions — but with a critical flaw discovered independently.
ORDER BY resolution_hours DESC LIMIT 3
NULL behaviour + text-sort flaw (independently identified)
Two real-world data bugs caught without prompting: (1) NULL values float unpredictably when sorted — NULL is not zero, it's the absence of a value. (2) Sorting text priority levels ('High','Medium','Low') alphabetically gives wrong ordering — 'Low' sorts before 'Medium' alphabetically. Fix: assign numeric values via CASE before sorting.
02
JOINs — Connecting Tables
Where SQL stops feeling like a spreadsheet
⚠ conditional pass
⚠ Conditional pass — review required
LEFT JOIN vs INNER JOIN distinction needs one unsupported review query before Module 01 checkpoint. Write both from memory before continuing.
⚡ Key mental model from this lesson
For two tables to JOIN, they must share a common key — a column that exists in both and means the same thing. At TCS: an Autosys job_id would need to appear in the ServiceNow tickets table to connect a job failure to its ticket. That shared key is the entire foundation of relational databases.
INNER JOIN
Returns only rows where the key exists in BOTH tables. If a row has no match on either side, it is excluded entirely. The strictest join — no orphans allowed.
SELECT * FROM jobs INNER JOIN tickets ON jobs.job_id = tickets.job_id
LEFT JOIN
Returns ALL rows from the left table, plus matching rows from the right. Where there's no match on the right, NULL fills the gap. Most common join in analytics — you want to keep all your base records even when some have no match.
SELECT * FROM jobs LEFT JOIN tickets ON jobs.job_id = tickets.job_id
RIGHT JOIN · FULL OUTER JOIN
RIGHT JOIN mirrors LEFT JOIN but keeps all right-table rows. FULL OUTER JOIN keeps everything from both sides, filling NULLs where matches are missing. Both are rare in practice — most teams rewrite as LEFT JOINs for readability.
SVG diagrams committed to GitHub
All four JOIN types documented as visual diagrams showing which rows survive each join. Committed to the analytics-engineer-journey repo with explanatory README collapsibles.
03
Subqueries and CASE Statements
Writing queries that reference other queries
✓ committed
⚡ Key mental model from this lesson
A subquery is just a query inside a query. The inner query runs first and produces a result — the outer query then uses that result as if it were a table or a value. CASE is SQL's version of if/else — it lets you create new columns based on conditional logic without touching the underlying data.
Subqueries in WHERE
Filter rows based on a calculation that requires a separate query. Classic use case: find all tickets with resolution time above average — you can't use WHERE resolution_hours > AVG(resolution_hours) directly because aggregate functions can't live in WHERE. The subquery runs the AVG first, then WHERE compares against it.
WHERE resolution_hours > (SELECT AVG(resolution_hours) FROM tickets)
Subqueries in FROM
Treat the result of a query as a temporary table and query it. Useful when you need to aggregate already-aggregated data — something a single GROUP BY can't do. The inner query runs first, produces a virtual table, and the outer query reads from it.
SELECT * FROM (SELECT priority, COUNT(*) as cnt FROM tickets GROUP BY priority) AS sub
Simple CASE · Searched CASE
Simple CASE compares one column to fixed values. Searched CASE evaluates full conditions. The fix for the text-sort flaw from Lesson 01 — assign numeric values to priority levels before sorting so High=1, Medium=2, Low=3 and ORDER BY works correctly.
CASE priority WHEN 'High' THEN 1 WHEN 'Medium' THEN 2 ELSE 3 END
COALESCE (NULL handling)
Returns the first non-NULL value from a list of arguments. Standard way to replace NULLs with a default value in output — critical for clean reporting and AI training data where NULLs can corrupt downstream processes.
COALESCE(resolution_hours, 0) — returns 0 if resolution_hours is NULL
04
SQL Toolkit — 8 Gap Concepts
Identified via DataLemur gap analysis · completing Module 01
▶ in progress
LIKE (pattern matching)
Match text values against patterns using wildcards. % matches any sequence of characters. _ matches exactly one character. Essential for searching messy real-world string data.
WHERE ticket_id LIKE 'INC%' — matches all incident tickets
BETWEEN (range filtering)
Filter rows within an inclusive range. Cleaner syntax than writing >= AND <=. Works on numbers, dates, and text.
WHERE resolution_hours BETWEEN 4 AND 12
DISTINCT (deduplication)
Remove duplicate rows from results. Critical for AI data pipelines — duplicate training examples skew model learning. DISTINCT in SELECT, or COUNT(DISTINCT column) for unique counts.
SELECT DISTINCT assigned_to FROM tickets
Date functions
Extract, compare, and calculate with dates. Every pipeline deals with timestamps. Key functions: DATE(), STRFTIME(), date arithmetic for calculating time between events.
String functions
UPPER(), LOWER(), LENGTH(), SUBSTR(), TRIM(), REPLACE(). How you clean and standardise messy text data before it enters a model or dashboard.
UNION · INTERSECT · EXCEPT
Combine results from multiple queries. UNION stacks rows together. INTERSECT returns only rows in both. EXCEPT returns rows in the first but not the second. Set operations on query results.
Arithmetic functions
ROUND(), ABS(), MOD(), basic math inside queries. How you calculate derived metrics directly in SQL without pulling data into Python first.
Self-joins
Join a table to itself using aliases. Used to compare rows within the same table — find all tickets created on the same day as another ticket, or compare an employee to their manager in a hierarchy.
SQLiteOnline.com DataLemur Weeks 1–2
🔒
Module 01 — Final SQL Checkpoint
Timed · unsupported · must pass before Python
locked
// planned checkpoint coverage
JOIN review — write INNER and LEFT from memory
Multi-condition WHERE with AND/OR/!=
Aggregation query with GROUP BY + HAVING
Subquery in WHERE and FROM
CASE statement with correct priority ordering
Toolkit concepts: LIKE, BETWEEN, DISTINCT, date function
🔒
Tableau Public — Dashboard Fundamentals
Your fastest bridge to Data Analyst hireability
locked
// planned topics — weeks 3–5
Connecting data sources · CSV · SQL output
Hiring managers can evaluate your work without reading a single line of code.
Building charts · bar · line · scatter
Filters · parameters · calculated fields
Dashboard layout + publishing to Tableau Public
3 published dashboards on public profile
Tableau Public (free)Official Tableau training (free)
🔒
Python for Data — pandas Foundations
Data-specific Python only · builds on existing base
locked
// planned topics — weeks 6–8
Reading CSVs · DataFrames · Series
Filtering · groupby · aggregation in pandas
Same logic as SQL GROUP BY — different syntax, same mental model.
Merging DataFrames (SQL JOIN equivalent)
Handling NULLs in pandas (NaN)
Writing cleaned data back to CSV
Kaggle Learn (free)Google Colab (free)
🔒
Pre-Baby Capstone — End-to-End Mini Project
Must exist on GitHub + Tableau Public before October
locked
// planned deliverables — weeks 9–10
Choose a real public dataset from Kaggle
Clean and inspect with Python + pandas
Query and analyse with SQL
Visualise in Tableau · publish to Tableau Public
Commit everything to GitHub with full README
Kaggle datasetsGitHubTableau Public
phase 2 — newborn survival mode · oct 2026 → feb 2027
Upcoming Maintain the habit. No new concepts. Streak over content. 30–45 min/day MAX
🍼
Survival Protocol
One SQL problem + one Python exercise · every weekday
upcoming
// daily protocol
DataLemur — one SQL problem (15 min)
Kaggle Learn — one Python micro-exercise (15 min)
5-day weekly streak = success. Nothing else counts.
phase 3 — return to learning · feb → jun 2027
Upcoming dbt + Cloud + AI data concepts = AE stack complete 2 hrs/day · ~160 hrs total
🔒
Advanced SQL + Data Modeling
Window functions · CTEs · Star schemas
locked
// planned topics — month 5
ROW_NUMBER · RANK · DENSE_RANK
Rank rows within groups without collapsing them. How you identify the first occurrence of an event per user in an AI dataset.
LAG · LEAD (time-series comparisons)
Compare a row to the row before or after it. Essential for monitoring model performance over time — did accuracy drop compared to last week?
CTEs (Common Table Expressions)
Named subqueries that make complex queries readable. The preferred pattern in dbt models.
Star schemas · fact + dimension tables
The data modeling pattern that underpins every data warehouse. Facts are events. Dimensions describe the context of those events.
Mode Analytics (free)🤖 AI relevance: high
🔒
dbt Core — The AE Differentiator
Free certification · the credential that gets AE interviews
locked
// planned topics — months 5–6
dbt models · staging → intermediate → mart layers
dbt tests · schema tests · custom tests
Data quality tests that run automatically. How AI teams catch corrupt training data before it reaches a model.
dbt documentation + lineage graph
dbt Fundamentals Certification (free)
dbt Learn (free)🤖 AI relevance: critical
🔒
BigQuery — Cloud Data Warehouse
Free sandbox · where AEs actually work
locked
// planned topics — month 7
BigQuery UI · sandbox setup · public datasets
Partitioning + clustering for query efficiency
Connect dbt to BigQuery · run transformations
BigQuery sandbox (free)🤖 AI relevance: high
🔒
AI Data Concepts — The Differentiator Layer
What separates AE from AI AE in every interview
locked
// planned topics — month 7
Training data quality — what makes data good vs bad for AI
Feature stores — what they are and why they exist
LLM evaluation datasets — how they're built
Model monitoring — detecting data drift
Data versioning with DVC basics
Eugene Yan blog (free)Hugging Face docs (free)🤖 AI relevance: critical
🔒
Capstone — Full AI Data Pipeline
Portfolio centerpiece · the project that gets interviews
locked
// planned deliverables — month 8
Raw public dataset → Python ingestion + cleaning
SQL modeling → dbt transformations → BigQuery
Tableau dashboard published publicly
AI training data analysis section in README
This one section makes the portfolio different from every other junior AE capstone.
Full GitHub commit history showing the build process
BigQuery + dbt + Tableau + GitHub🤖 AI relevance: critical
// nabiya_roadmap_v3 · private · last updated August 2026
⎇ github ◎ portfolio