DQL - Advanced Analytics

CTEs, Window Functions & Global Aggregations

In a global retail powerhouse, simply "selecting" data is not enough. To stay ahead of competitors, we must perform complex analysis at scale. How do we compare a single store's performance against its regional average? How do we rank products across multiple currencies?

This chapter deep-dives into Data Query Language (DQL). We will master Common Table Expressions (CTEs) for readable logic, Window Functions for sophisticated ranking, and advanced aggregations to transform millions of transactions into actionable business intelligence.

CTEs: Clean Logic for Complex Problems

Common Table Expressions (CTEs), defined using the WITH keyword, are temporary result sets. In retail analytics, we often have "multi-step" logic. For example: First calculate total tax per region, THEN calculate the average tax across all regions.

CTEs act like "variables" for your queries, making them much easier to read and maintain than deeply nested subqueries. They are the standard for professional SQL development in global firms.

SQL
WITH RegionalAverages AS (    SELECT region, AVG(total_sales) as avg_regional_sales    FROM store_performance    GROUP BY region)SELECT     s.store_name,     s.region,     s.total_sales,    r.avg_regional_sales,    (s.total_sales - r.avg_regional_sales) as varianceFROM store_performance sJOIN RegionalAverages r ON s.region = r.regionORDER BY variance ASC;

Window Functions: Analytics without Collapsing

Traditional GROUP BY collapses your data into a single row. But what if you want to see the individual transaction AND the total sales for that day side-by-side? That's where Window Functions shine.

Using the OVER() clause, we can perform calculations across a "window" of rows. This is essential for:

  • Running Totals: Seeing how revenue grows day-by-day.
  • Ranking: Finding the #1 salesperson in every branch.
  • Lead/Lag: Comparing this month's stock to last month's immediately.

SQL
SELECT     sale_date,     amount,    SUM(amount) OVER (ORDER BY sale_date) as running_totalFROM sales_table;

Advanced Aggregation: Finding the Signal

Aggregations like SUM, AVG, and COUNT are the bread and butter of retail reports. However, power users leverage the HAVING clause to filter grouped data. While WHERE filters individual rows *before* they are grouped, HAVING filters the results *after* the math is done.

Example: Find only the warehouses that have more than 50,000 items in stock.

SQL
SELECT warehouse_id, SUM(stock_count) as totalFROM inventoryGROUP BY warehouse_idHAVING SUM(stock_count) > 50000;
SQLRuns entirely in your browser — nothing is sent to a server.

Practice Questions

Question 1

Which keyword is required to start a Common Table Expression (CTE)?

  • START
  • WITH
  • GIVE
  • TEMP

Question 2

In a window function, which clause is used to define the 'subset' of data (like grouping by Category)?

  • GROUP BY
  • PARTITION BY
  • DIVIDE BY
  • SPLIT

Question 3

When should you use HAVING instead of WHERE?

  • To filter by individual IDs
  • When filtering based on an aggregate function like SUM or AVG
  • To speed up the query
  • Only when using Joins

Question 4

Which function would you use to see the revenue of the 'previous' row in your current row?

  • BACK
  • LAG
  • PREV
  • LAST

Question 5

What happens if you use a Window Function without a PARTITION BY clause?

  • The query fails
  • The function treats the entire result set as a single partition
  • It defaults to the first row
  • It only ranks the last 10 rows