Enoch Adefemi

Analyst

Data analyst using SQL and Excel to answer operational and financial questions for retail and logistics scenarios

Scores reflect independent, automated grading of simulated business tasks completed on DataSimHQ.

Graded projects
22
Average best score
89/100
Career level
Analyst
Core tool stack
Excel (11) · SQL (10) · email (1)

About

Working through retail and logistics scenarios on a structured simulation platform, I have practised translating stakeholder questions into clean SQL queries and Excel models. My work has covered revenue reconciliation, complaint volume analysis, and order-table profiling, using SUMIFS, window functions, and aggregation logic to produce decision-ready outputs.

Across these projects I have focused on accuracy first: matching expected totals, choosing formulas that stay live rather than hardcoding values, and writing queries that surface the right number in the fewest steps. I also practise flagging data quality issues when I spot them, such as duplicate records and inconsistent category labels, because clean inputs shape reliable findings.

Skills

SQL

  • SQL GROUP BY with COUNT(*) aggregation
  • Window function SUM(COUNT(*)) OVER () for inline totals
  • ROUND() for board-readable numeric output
  • Timestamp casting with ::date in PostgreSQL
  • Cents-to-naira conversion using SUM / 100.0
  • ORDER BY on aggregated column for ranked output
  • Percentage calculation as COUNT(*) * 100.0 / window total

Excel

  • SUMIFS with date range bounds using EOMONTH
  • Multi-criteria exclusion with SUMIFS and <> pairs
  • Live gap formula as =B2-B3 rather than hardcoded value
  • Nigerian Naira number formatting with thousand separators
  • Data audit: identifying duplicates and column inconsistencies

Retail · SQL

Profiling order statuses to support a revenue discrepancy investigation

Independent grading: 97/100(verify, opens in a new tab)

Problem

Meridian Retail (simulated retailer) CFO Nura Ibrahim flagged a revenue discrepancy and needed a baseline picture of the orders table before filtering could begin. The specific question was: what distinct order statuses exist, and how many orders carry each one?

What I did

A single SELECT with COUNT(*) and GROUP BY status against retail.orders produced the full status breakdown in one pass. Ordering by the count descending was a deliberate choice so the dominant status would appear at the top without any additional sorting step. The explicit schema prefix retail.orders was kept in place even though the search path was already set, to keep the query unambiguous in any session context.

Finding

All 7 distinct statuses were present, with delivered accounting for 14,061 orders as the dominant status, and cancellations, returns, and refunds visible as the revenue-impacting tail.

Outcome

The output gave Nura a ranked, complete status map to guide the next filtering step in her investigation, with no manual counting or pivoting required.

Next step

A useful follow-on would be to calculate the naira value associated with each status, so the revenue impact of cancelled, returned, and refunded orders can be compared directly rather than just by order count.

  • SQL GROUP BY with COUNT(*) aggregation
  • ORDER BY on aggregated column for ranked output
  • Explicit schema prefix usage in PostgreSQL

Retail · Excel

Reconciling gross and net October revenue in Excel for finance cross-check

Independent grading: 95/100(verify, opens in a new tab)

Problem

Meridian Retail CFO Nura Ibrahim needed an October 2023 revenue figure in Excel to cross-check against the Finance system. The request specified both a gross figure covering all statuses and a net figure with cancelled, returned, and refunded orders excluded, along with the gap between the two.

What I did

Two SUMIFS formulas were built against the Orders sheet, bounding the date range with EOMONTH to capture the full month reliably regardless of the exact day count. The net revenue formula applied three separate criteria pairs, each using a not-equal operator to exclude one of the three disqualifying statuses in a single expression. The gap in B4 was written as =B2-B3 so it stays live if either source figure is recalculated. All three cells were formatted with the NGN Naira code and thousand separators to meet the display requirement exactly.

Finding

Gross October revenue was NGN 56,876,792.48, net revenue was NGN 38,450,382.35, and the gap attributable to cancelled, returned, and refunded orders was NGN 18,426,410.13.

Outcome

Nura received a single-sheet view she could compare directly against the Finance system, with live formulas that would update if the underlying data changed and Naira formatting already in place for reporting.

Next step

Breaking the NGN 18,426,410.13 gap further by status would show whether cancellations, returns, or refunds drive the larger share, which would point to different operational fixes.

  • SUMIFS with date range bounds using EOMONTH
  • Multi-criteria exclusion with SUMIFS and <> pairs
  • Live gap formula as =B2-B3 rather than hardcoded value
  • Nigerian Naira number formatting with thousand separators
  • Data audit: identifying duplicates and column inconsistencies

Logistics · Email

First-read complaint summary for a customer experience lead ahead of a board meeting

Independent grading: 62/100(verify, opens in a new tab)

Problem

FlowRoute Logistics (simulated logistics company) Head of Customer Experience Funmi Alade needed a short, phone-readable email before a Friday meeting. She asked for the top complaint category with its share of total, an honest read on whether one hub stood out as worst, and a single memorable number she could quote to a colleague.

What I did

The response led with the top category and its percentage, which directly answered the first item. For the hub question, the data showed no clear outlier, so rather than naming one arbitrarily, I reported the range of 35 to 37 complaints per 1,000 shipments to show the spread was narrow. The email was kept under 150 words to match the stated reading context. The third item, the single memorable number Funmi requested, was not included, which the reviewer identified as a gap in the submission.

Finding

Lost Complaint was the leading category at 25.57% of all complaints, and hub performance was broadly consistent rather than concentrated in one location.

Outcome

Funmi received a direct, honest picture of the top category and hub spread before her meeting, though the submission did not provide the one memorable standalone number she had specified.

Next step

Identifying one concrete operational metric, such as the absolute complaint count for the single worst month across all hubs, would have given Funmi the quotable number the submission missed.

  • Percentage calculation as COUNT(*) * 100.0 / window total
  • Stakeholder-appropriate written communication under a word limit
  • Qualitative data interpretation when no single outlier exists

Logistics · SQL

Complaint volume breakdown by category for a board pack

Independent grading: 97/100(verify, opens in a new tab)

Problem

FlowRoute Logistics Head of Customer Experience Funmi Alade needed three things for an upcoming board pack: total complaint volume, a ranked breakdown by category with percentages, and a one-sentence recommendation on which category to lead with. The source was the logistics.complaints table with one row per complaint.

What I did

Rather than using a subquery or CTE to get the grand total separately, I nested COUNT(*) inside SUM(...) OVER () to produce the denominator inline, which keeps the query to a single pass. Dividing the per-category count by that window total and multiplying by 100.0 avoids integer truncation, and ROUND(..., 1) trims the result to one decimal for board-pack readability. Carrying TOTAL_COMPLAINTS as a column in every output row means the reader can verify the denominator without a separate query. A comment at the end of the script delivered the one-sentence board recommendation in plain language.

Finding

Lost parcels were the single largest complaint driver at 25.6% of 64,737 total complaints, though all four categories were within roughly one percentage point of each other.

Outcome

Funmi received a ranked, percentage-labelled table with the grand total visible in every row, plus a written recommendation she could quote directly to the board.

SELECT
 SUM(COUNT(*))OVER() AS TOTAL_COMPLAINTS,
 category,
 COUNT(*) AS CategoryComplaint,
 ROUND(COUNT(*) * 100.0/SUM(COUNT(*)) OVER (), 1) AS ComplaintPercentage
FROM complaints
GROUP BY category
ORDER BY CategoryComplaint DESC

-- Lead with 'Lost' parcels -- at 25.6% of all complaints, it is the single largest driver of customer dissatisfaction.

SUM(COUNT(*)) OVER () computes the grand total by summing the per-group counts produced by GROUP BY in one pass, avoiding a subquery and making the percentage denominator visible as a column in every output row.

Next step

Filtering complaints by date to see whether the Lost category share has grown, stayed flat, or narrowed over recent months would tell Funmi whether this is a worsening trend or a stable baseline.

  • Window function SUM(COUNT(*)) OVER () for inline totals
  • Percentage calculation as COUNT(*) * 100.0 / window total
  • ROUND() for board-readable numeric output
  • SQL GROUP BY with COUNT(*) aggregation
  • ORDER BY on aggregated column for ranked output

Retail · SQL

Baseline order table summary: count, date range, and total revenue in naira

Independent grading: 97/100(verify, opens in a new tab)

Problem

Meridian Retail CFO Nura Ibrahim needed a single-row baseline summary of the orders table before any filtering began. The request covered four metrics: total order count, earliest order date, latest order date, and total revenue in naira.

What I did

COUNT(*) returns the full row count without any filter condition, which is the correct baseline measure. Wrapping MIN and MAX of the created_at timestamp column in ::date casts strips the time component, producing clean calendar dates rather than datetime strings. The revenue calculation divides SUM(total_cents) by 100.0 rather than 100 to force floating-point division and preserve the kobo component, with ROUND(..., 2) applied to hold the result to two decimal places. Descriptive aliasing, using Total_Revenue_In_Naira instead of a shorter abbreviation, was a deliberate choice to make the output self-explanatory without a data dictionary.

Finding

The orders table contained 23,572 orders spanning 2021-01-12 to 2024-12-31, with total revenue of NGN 2,305,853,142.45.

Outcome

Nura received a clean single-row baseline she could use as the denominator for every subsequent filtered query in the investigation.

SELECT COUNT(*) AS Total_Orders,
Min(created_at)::date AS Earliest_Order,
MAX(created_at)::date AS Latest_Order,
ROUND(SUM(total_cents) / 100.0, 2) AS Total_Revenue_In_Naira
FROM retail.orders

The ::date cast on MIN and MAX removes the timestamp portion for clean date output, and dividing by 100.0 instead of 100 ensures the division returns a decimal result before ROUND is applied.

Next step

Repeating the same four metrics filtered to only revenue-impacting statuses, cancelled, returned, and refunded, would immediately show what share of the NGN 2,305,853,142.45 total is at risk.

  • SQL GROUP BY with COUNT(*) aggregation
  • Timestamp casting with ::date in PostgreSQL
  • Cents-to-naira conversion using SUM / 100.0
  • ROUND() for board-readable numeric output
  • Explicit schema prefix usage in PostgreSQL

Additional projects

Customer Analytics

  • Monthly customer acquisition trend chart for investor presentation · Excel · 88/100
  • Acquisition channel performance summary for investor deck · Excel · 72/100
  • 24 month new customer acquisition trend analysis · SQL · 88/100
  • Definitive customer count for investor reporting · SQL · 90/100
  • Customer acquisition breakdown by channel · SQL · 95/100

Data Analysis

  • Meridian data file scoping and familiarization · Excel · 72/100

Data Quality

  • Customer count validation and deduplication audit · Excel · 92/100
  • Duplicate customer detection and name match validation · Excel · 95/100
  • Failed shipment attempt cap compliance audit · Excel · 91/100
  • Monthly shipment failure rate correction · Excel · 95/100
  • Delivery attempt cap policy compliance audit · SQL · 88/100

Financial Reporting

  • October revenue discrepancy investigation across systems · SQL · 88/100
  • Q4 revenue breakdown by order status · Excel · 92/100
  • Cancelled order revenue gap analysis · SQL · 97/100

Operations Analytics

  • Hub level complaint breakdown and categorization · Excel · 88/100
  • Hub performance ranking by delivery rate and complaints · Excel · 90/100
  • Hub underperformance ranking by delivery and complaint metrics · SQL · 88/100