Back to Blog

Why Your AI's OR Filter Returns Way Too Many Rows

Asked for paid orders in the US and got every paid order on earth plus a pile of unpaid US ones. AND binds tighter than OR — without parentheses, the filter you said is not the filter that ran.

You ask for "paid orders in the US, or any refunded orders." The list comes back huge — every paid order worldwide, plus some refunds, plus things that match neither thing you thought you said. The SQL looks almost right. AND binds tighter than OR, and nobody put parentheses around the groups.

What the database actually heard

English: paid AND (US or refunded)
Un-parenthesized SQL often comes out as:

WHERE status = 'paid' OR country = 'US' AND refunded = true

Which the database reads as:

WHERE status = 'paid' OR (country = 'US' AND refunded = true)

That is "every paid order on earth, plus US refunds." Not "paid US orders, plus refunds." Valid SQL. Wrong question. No error.

This is the opposite failure mode from NULL filters dropping rows or a LEFT JOIN collapsing to INNER. Those under-count. This one over-includes because OR leaked across a clause you meant to keep tight.

Why the AI writes it this way

The model is translating a spoken sentence. Spoken sentences use commas and emphasis for grouping. SQL uses parentheses. If the prompt doesn't say "group these conditions," the model often dumps the words in order and lets precedence decide — the same way 3 + 4 * 5 is 23, not 35, whether or not that was the intent.

describe_table does not help. The columns are real. The types are fine. The logic is just grouped wrong.

How to catch it

Ask for the count and the parenthesized version of the filter in English:

Show the SQL.
Restate the WHERE in English with parentheses:
  (A and B) or C
versus
  A or (B and C)
Which one did you run? What's the COUNT(*) for each?

If those two counts differ, you found it. Keep the one that matches the question you actually asked.

The fix is punctuation, not a different function

-- what you probably meant
WHERE (status = 'paid' AND country = 'US')
   OR refunded = true

-- what often ran
WHERE status = 'paid'
   OR country = 'US' AND refunded = true

Same words. Different grouping. Different business.

The prompt that heads this off

When a WHERE mixes AND and OR, always add parentheses around each
group. Don't rely on AND binding tighter than OR. After writing the
filter, restate it in English with those parentheses so I can confirm.

The short version

AND is multiplication; OR is addition. An un-parenthesized mix is valid SQL and often the wrong sentence. If a filter came back "everything plus extra," look at the OR before you look at the join.


Read-only MCP gateway: mcpserver.design.

Related reading: