HAVING Clause

Use the HAVING clause to filter grouped results from grouped columns, aggregate functions, or grouping functions.

HAVING follows this syntax: HAVING {search-condition}.

A search condition can contain boolean expressions, comparison operators, and scalar functions.

This query returns groups of cities that contain furniture stores and their counts. The HAVING clause filters for the Furniture category.

CategoryCitycnt
FurnitureAkron2
 Alexandria3
 Allen1
 Allentown1
 Amarillo4
 Anaheim8
 Andover1
 Apopka1
 Apple Valley2
 Arlington13

You can also write this query using WHERE.

In the logical execution of a SELECT statement, WHERE filters out rows before any grouping or aggregate function runs. In this example, it selects the rows that can be passed to the aggregate function count(). The WHERE clause comes before a GROUP BY statement. With HAVING, the filtering occurs after all of the rows have been passed to count(). HAVING always comes after a GROUP BY statement. Both HAVING and WHERE run before projection.

This query returns groups of cities that have more than 150 stores in each category. The HAVING clause filters out values greater than 150 in the aggregate column, cnt.

CategoryCitycnt
FurnitureLos Angeles154
 New York City192
Office SuppliesHouston231
 Los Angeles443
 New York City552
 Philadelphia312
 San Francisco322
 Seattle249
TechnologyNew York City171

Using HAVING with an aggregate function automatically implies GROUP BY(). These two queries return the same result.

TotalProfit
286,397.02

Here’s a simple example of how to use HAVING with GROUP BY ROLLUP. The query returns the profit for each Sub-Category, rolls them up into subtotals of each Category, and then sums up the grand total. Here, HAVING filters on positive profits.

CategorySub-CategoryTotalProfit
FurnitureChairs26,590.17
 Furnishings13,059.14
 -18,451.27
Office SuppliesAppliances18,138.01
 Art6,527.79
 Binders30,221.76
 Envelopes6,964.18
 Fasteners949.52
 Labels5,546.25
 Paper34,053.57
 Storage21,278.83
 -122,490.8
TechnologyAccessories41,936.64
 Copiers55,617.82
 Machines3,384.76
 Phones44,515.73
 -145,454.95
 -286,397.02

In SQL for CRM Analytics, you can use HAVING() with the GROUP BY ROLLUP subclause and the GROUPING() function. You can use GROUPING() with ROLLUP only; you can’t use it on its own.

This example uses the GROUPING() function with the HAVING() function to filter for the subtotals of each category and return the grand total. The GROUPING() function returns 1 for null values that are the result of a ROLLUP, and not null values in your dataset. Here, by setting GROUPING(Sub_Category) = 1, we know that these Sub-Category values refer to the subtotals of each category.

CategorySub-CategoryTotalProfit
Furniture-18,451.27
Office Supplies-122,490.8
Technology-145,454.95
--286,397.02