Intro to SQLfor Organizing
Subsection 6.3

HAVING and LIKE

~4 min

Reading

WHERE filters rows before grouping.

HAVING filters groups after grouping.

That difference matters.

Use WHERE when you want to decide which rows enter the summary.

Use HAVING when you want to filter the grouped result.

Example:

SELECT zip_code, COUNT(*) AS signup_count
FROM `team.signups`
WHERE signup_date >= '2026-04-01'
GROUP BY zip_code
HAVING signup_count >= 10
ORDER BY signup_count DESC;

This query:

  1. Starts with signups on or after April 1.
  2. Groups them by zip code.
  3. Counts signups in each zip code.
  4. Keeps only zip codes with at least 10 signups.
  5. Sorts the result from highest to lowest.

The slide deck also introduces LIKE for string pattern matching.

LIKE helps you search for patterns in text fields. It is commonly used with wildcard characters:

  • % matches any number of characters.
  • _ matches a single character.

Examples:

WHERE last_name LIKE 'G%'

This finds values that start with G.

WHERE notes LIKE '%transportation%'

This finds values that contain the word transportation.

The slide deck notes that pattern matching is useful for text data, cleaning, and preparation. In civic data, this can help find notes, source labels, tags, or categories that were entered inconsistently.

Learner action

Add either HAVING or LIKE to a practice query. Then explain what it changes in the result.

HAVING : filter the groups, not the rows

  • WHERE filters rows before grouping.
  • HAVING filters groups after aggregation.

"Only zip codes with more than 50 signups"

SELECT zip_code, COUNT(*) AS signups
FROM `project.dataset.signups`
WHERE created_at >= '2026-01-01'   -- filters rows
GROUP BY zip_code                  -- collapses rows into groups
HAVING COUNT(*) > 50               -- filters groups
ORDER BY signups DESC
LIMIT 25;

The cleanest way to remember: WHERE is for rows, HAVING is for groups.

LIKE : text pattern matching

  • % matches any sequence of characters (including zero).
  • _ matches a single character.
  • LIKE is case-sensitive in BigQuery : wrap in LOWER() for case-insensitive search.

Examples

-- All names starting with "Mar"
SELECT name, SUM(number) AS births
FROM `bigquery-public-data.usa_names.usa_1910_current`
WHERE name LIKE 'Mar%'
GROUP BY name
ORDER BY births DESC
LIMIT 20;

-- All names ending in "ia"
WHERE name LIKE '%ia'

-- 4-letter names starting with "An"
WHERE name LIKE 'An__'

HAVING is WHERE for grouped results : it filters AFTER the GROUP BY runs. LIKE is for matching text with wildcards. Combine them to find counties with a lot of Democrats.

Action: If your grouped query returns too many tiny groups, add HAVING COUNT(*) >= N. If your question involves text patterns, add a LIKE.