Brightlane's North America retention team is running a reactivation campaign targeting active customers based in the US or Canada.
Write a query to return the name and country of every qualifying customer.
Assumptions:
- Active customers are identified by
is_active = true. - North American customers are identified by
country = 'US'orcountry = 'CA'. - A qualifying customer must be active and based in one of the two North American countries.
Output:
- One row per qualifying customer, with columns
nameandcountry.
Schema · ecommerce 5 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
SELECT
name,
country
FROM
customers
WHERE
is_active = TRUE
AND (
country = 'US'
OR country = 'CA'
) The shape
The parentheses around the country OR are the load-bearing piece. They keep AND and OR from interleaving, so the filter reads as "active, AND in one of these two countries" rather than the precedence default of "active and US, OR Canadian at all."
Clause by clause
SELECT name, countryreturns the customer and the country they're being targeted in. Keepingcountryin the output makes the filter easy to verify.FROM customersreads the customer table.WHERE is_active = true AND (country = 'US' OR country = 'CA')is the compound filter.is_active = truekeeps active rows.(country = 'US' OR country = 'CA')is a single grouped condition — a row passes if either equality is true. The outerANDrequires both the active flag and the country group to hold on the same row. So an active US customer passes (active is true, US matches), an active Canadian passes (active is true, CA matches), an inactive US customer is dropped (the active flag is false), and an active UK customer is dropped (neither country equality is true).
Why the parentheses are not optional
Without them, the query reads is_active = true AND country = 'US' OR country = 'CA'. AND binds tighter than OR, so PostgreSQL groups it as (is_active = true AND country = 'US') OR country = 'CA'. That keeps active US customers (the left side), and then keeps every Canadian customer regardless of active status (the right side stands alone). An inactive Canadian customer would pass — which is the opposite of what a reactivation campaign needs.
The parentheses bind the OR into a single unit before the AND applies. That's what produces the intended logic: active is required, and country membership is required, on the same row.
The trap
Mixing AND and OR without parentheses lets PostgreSQL's precedence rules quietly group the conditions for you. The query runs, returns a set of customers that looks roughly right at a glance, and the inactive Canadians ride through to a "reactivation" campaign that should never have included them. There's no error, no warning, no signal that the precedence isn't what you meant. Any time AND and OR appear in the same WHERE, parenthesise the OR group so the binding is explicit and the query encodes the business logic, not the default precedence.
You practiced parenthesising an OR group inside an AND to control evaluation order. NOT binds tightest, then AND, then OR — so any time a compound WHERE mixes AND with OR, parentheses are how you make sure PostgreSQL groups the conditions the way you intended.