GROUP BY and HAVING – Understanding & Practice
SQL Study Notes – AdventureWorksDW2017
This page covers GROUP BY, HAVING, LEFT JOIN + IS NULL, EXISTS, IN, and comparison between IN and LIKE.
Key Concepts
WHERE vs HAVING
- WHERE filters rows before grouping.
- HAVING filters groups after grouping and aggregation.
IN vs LIKE
- IN → Used when you have a list of exact values (e.g., specific categories or years).
- LIKE → Used for partial text matching with wildcards (% and _).
SQL Order of Operations
- FROM + JOINs
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
Practice Questions with Solutions
Question 1 – GROUP BY + Date
List all employees and the most recent sales date. Show full name in one column. Format date as mm/dd/yyyy.
Solution:
SELECT
CONCAT(E.FirstName, ' ', ISNULL(E.MiddleName, ''), ' ', E.LastName) AS FULLNAME,
CONVERT(VARCHAR, MAX(FIS.OrderDate), 101) AS MOSTRECENTORDERDATE
FROM DimEmployee E
LEFT JOIN FactInternetSales FIS ON E.EmployeeKey = FIS.SalesTerritoryKey
GROUP BY E.FirstName, E.MiddleName, E.LastName
ORDER BY MOSTRECENTORDERDATE DESC;
Question 2 – GROUP BY + HAVING
For each sales territory, show number of transactions and total sales. Only show territories with more than 1000 transactions.
Solution:
SELECT
ST.SalesTerritoryRegion,
COUNT(*) AS NUMBEROFTRANSACTIONS,
SUM(FIS.SalesAmount) AS TOTALSALES
FROM FactInternetSales FIS
JOIN DimSalesTerritory ST ON FIS.SalesTerritoryKey = ST.SalesTerritoryKey
GROUP BY ST.SalesTerritoryRegion
HAVING COUNT(*) > 1000
ORDER BY TOTALSALES DESC;
Question 3 – LEFT JOIN + IS NULL
Find customers who have never placed an order.
Solution:
SELECT
DC.CustomerKey,
DC.FirstName,
DC.LastName
FROM DimCustomer DC
LEFT JOIN FactInternetSales FIS ON DC.CustomerKey = FIS.CustomerKey
WHERE FIS.CustomerKey IS NULL;
Question 4 – EXISTS
Find customers who have placed at least one order.
Solution:
SELECT
DC.CustomerKey,
DC.FirstName,
DC.LastName
FROM DimCustomer DC
WHERE EXISTS (
SELECT 1
FROM FactInternetSales FIS
WHERE FIS.CustomerKey = DC.CustomerKey
);
Question 5 – IN Operator
Show total sales for products in categories ‘Bikes’ or ‘Clothing’.
Solution:
SELECT
C.EnglishProductCategoryName,
SUM(FIS.SalesAmount) AS TOTALSALES
FROM FactInternetSales FIS
JOIN DimProduct P ON FIS.ProductKey = P.ProductKey
JOIN DimProductSubcategory PS ON P.ProductSubcategoryKey = PS.ProductSubcategoryKey
JOIN DimProductCategory C ON PS.ProductCategoryKey = C.ProductCategoryKey
WHERE C.EnglishProductCategoryName IN ('Bikes', 'Clothing')
GROUP BY C.EnglishProductCategoryName;
Question 6 – LIKE Operator
Find all customers whose last name starts with ‘S’.
Solution:
SELECT
FirstName,
LastName
FROM DimCustomer
WHERE LastName LIKE 'S%';
IN vs LIKE – Quick Comparison
| Operator | When to Use | Example |
|---|---|---|
| IN | Exact match from a list | EnglishProductCategoryName IN (‘Bikes’, ‘Clothing’) |
| LIKE | Pattern / partial match | LastName LIKE ‘S%’ (starts with S) |
Practice these patterns well. They appear often on the final exam.