Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

Why does an OR condition return extra rows when I combine it with AND?

Quick answer

SQLite evaluates AND before OR. So priority = 'high' OR owner = 'Mia' AND done = 0 means priority = 'high' OR (owner = 'Mia' AND done = 0). It includes every high-priority row, even completed ones. If you want either high priority or Mia’s tasks, but only when unfinished, write (priority = 'high' OR owner = 'Mia') AND done = 0.

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

Why does my SQLite query return completed tasks when I thought done = 0 applied to both sides of an OR? I’m filtering a task list.

Geez

It’s likely a grouping issue. SQLite gives AND higher precedence than OR, so it reads A OR B AND C as A OR (B AND C). A row is kept when its WHERE expression is true. [S1]

That means your high-priority condition can match on its own; the done = 0 restriction applies only to the other side of the OR. Parentheses tell SQLite which combined condition you mean.

Follow-up question

Can you show exactly what that means with a small task list?

Geez

Assume this invented data, where done is 1 for completed and 0 for unfinished:

id | priority | owner | done
1  | high     | Leo   | 1
2  | high     | Mia   | 0
3  | low      | Mia   | 0
4  | high     | Noor  | 0
5  | low      | Noor  | 0

The unparenthesized filter is:

SELECT id FROM tasks
WHERE priority = 'high' OR owner = 'Mia' AND done = 0;

SQLite groups it as priority = 'high' OR (owner = 'Mia' AND done = 0). It returns IDs 1, 2, 3, and 4. ID 1 is completed, but it passes because its priority is high; IDs 2 and 4 pass as high priority, and ID 3 passes as Mia’s unfinished task. ID 5 matches neither side.

Follow-up question

I want high-priority tasks or Mia’s tasks, but only if the task is unfinished. What should I change?

Geez

Group the two alternatives first, then apply the unfinished condition to the whole group:

SELECT id FROM tasks
WHERE (priority = 'high' OR owner = 'Mia') AND done = 0;

This returns IDs 2, 3, and 4. The parentheses make the OR a single condition; the trailing AND means every matching row must also have done = 0. ID 1 is now excluded because it is completed, and ID 5 is excluded because it is neither high priority nor owned by Mia.

A useful way to check your intent is to say the rule aloud: “(high priority or owned by Mia) and unfinished.” The parentheses in the SQL mirror that grouping.

Follow-up question

Would adding parentheses around the Mia condition fix it? How can I avoid this kind of mistake in other filters?

Geez

Writing priority = 'high' OR (owner = 'Mia' AND done = 0) makes SQLite’s default grouping explicit, but it does not change which rows match: it still allows any high-priority task, including completed ones. To require unfinished status for both alternatives, put parentheses around the OR expression, as in the second query. [S1]

Before running a mixed filter, label the intended groups and compare them with the parentheses. Test a few rows that should pass and a few that should fail—especially rows that match just one side of the OR. This example uses invented data; your actual result rows depend on your table contents. The cited SQLite precedence rule explains the grouping, not what data exists in your database.

A practical checklist

  • Write the intended rule in plain language, including words such as “both,” “either,” and “only if.”

  • Mark which conditions belong together before writing the SQL.

  • Add parentheses around each OR group when an AND condition should apply to the whole group.

  • Check a row that matches only the first OR condition and a row that matches only the second.

  • Check a completed row that otherwise matches, to confirm whether it should be included.

A few more useful answers

Does adding parentheses always change the results?

No. Parentheses can make the existing precedence explicit without changing the grouping or results. They change results when they group conditions differently, as in moving parentheses around the OR expression.

What does `A OR (B AND C)` mean in plain language?

A row passes if A is true, or if both B and C are true. C does not restrict rows that already pass A.

What is a quick way to verify the filter?

Use a small set of rows representing the important cases: each OR alternative on its own, both alternatives, and a row that matches an alternative but fails the shared condition. Compare those expected cases with the query results.

Sources

References used for this guide.

  1. [S1] SQLite SQL Language Expressions — operator precedence
    sqlite.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work