Photo by Daniel Gonzalez on Unsplash

Fix WHERE clause AND/OR/NOT confusion with truth tables

Today on the #sqlhelp hashtag, I found this outstanding question about logic in the WHERE clause, and pounced on it:

This is not at all unusual, and I find that my early love of algebra (and brief stuies in circuitry logicreally comes in handy for working these things out.

It certainly seems like these two options should be equivalent, right? WHERE NOT (“and-ed” truth) should be equivalent to WHERE (opposite of that truth).

Shouldn’t this… …be the same as this? (Answer)
WHERE NOT (Id = 1
AND ForeignId  = ‘TD75R’)
WHERE NOT ID = 1
AND NOT ForeignID = TD75R
No, actually.
WHERE (Id <> 1
AND  ForeignId  <> ‘TD75R’)
WHERE ID <> 1
AND ForeignID <> TD75R
Yes, actually!

 

The problem comes in, oddly enough, where we kind of assume that the NOT can be multiplied against each of the inner items, just like x(4 + 2) = 4x + 2x. That’s the distributive property of algebra, by the way.

It can’t. Logic gates work slightly different than plain-Jane algebra, and “NOT” is a weird force anyway. Let’s work all this out by hand, using a truth table.

How to work out WHERE clause logic manually

It’s really fine if all the circuitry and algebra stuff makes no sense to you. We’re going to use a tried-and-true method to figuring out how these things will come out.

For a truth table, you just put in every combination of input types – meaning, inputs that will evaluate to true, and those that evaluate to false – and work out how the clause will evaluate it overall.

What do I mean? Well, we have two inputs for the questions above: StatusID and UserForeignID, which I’ll shorten to ID and ForeignID to save characters. Logically speaking:

  • ID can either be equal to 1, or to a value other than 1.
  • ForeignID can either be equal to TD75R, or to a value other than TD75R.

So the possible scenarios are as follows:

ID ForeignID In English…
1 TD75R Both values are what we’re looking for. 
1 Some value that’s not TD75R, like “X” Only one value is what we’re looking for.
2 TD75R Only one value – the other one – is what we’re looking for.
2 Some value that’s not TD75R, like “X” Neither value is what we’re looking for.

 

Now, we take that table, and evaluate the outcome for each of the two different clauses. Remember two things. One, that SQL Server evaluates what’s in the parentheses first! And two, that “true” ends up meaning “yes, I would like this row returned”, and “false” means the row is excluded from the result set.

Truth table for “WHERE NOT (Id = 1 AND ForeignId  = ‘TD75R’)”

Here are the inputs, work shown, and result from the clause WHERE NOT (Id = 1 AND ForeignId  = ‘TD75R’):

ID ForeignID Show your work Result
1 TD75R WHERE NOT (True AND True) =
WHERE NOT (True) ==
False
1 Some value that’s not TD75R, like “X” WHERE NOT (True AND False) =
WHERE NOT (False) ==
True
2 TD75R WHERE NOT (False AND True) =
WHERE NOT (False) ==
True
2 Some value that’s not TD75R, like “X” WHERE NOT (False AND False) =
WHERE NOT (False) ==
 True

 

Truth table for “WHERE (Id <> 1 AND  ForeignId  <> ‘TD75R’)”

Here are the inputs, work shown, and result from the clause WHERE (Id <> 1 AND  ForeignId  <> ‘TD75R’):

ID ForeignID Show your work Result
1 TD75R WHERE (False AND False) =
WHERE (False) ==
False
1 Some value that’s not TD75R, like “X” WHERE (False AND True) =
WHERE (False) ==
False
2 TD75R WHERE (True AND False) =
WHERE (False) ==
False
2 Some value that’s not TD75R, like “X” WHERE (True AND True) =
WHERE (True) ==
True

 

Results

When we compare the two truth tables, we see that the same inputs produce entirely different results! Those two clauses are not equivalent.

Technically, what’s the difference?

The answer, in case you’re curious, is that the first clause – the WHERE NOT clause – is officially a NAND gate. It literally takes the result of the inner outputs (which are AND-ed, by the way)…and reverses them. So the only possible way to get the result “False”, is if all the inputs are “True”.

The second clause is NOT a NAND gate. It’s just a regular AND gate, where the inputs happen to have a “not equals” as the deciding function.

Make sense?

No?

Then stick to the truth tables, like I do.

The problem gets bigger with more ANDs and ORs

Just be sure you get EVERY POSSIBLE LOGICAL COMBINATION (though, not every possible input…that’d be silly and impossible), meaning every combination of “evaluates to true” and “evaluates to false” for each and every one of your inputs. Note that this gets more complex as the inputs increase. For example, if the clause above had been “WHERE NOT (Id = 1 AND ForeignId  = ‘TD75R’ AND val=20)”

So the possible scenarios are as follows:

ID ForeignID val In English…
1 TD75R 20 All values are what we’re looking for. 
1 Some value that’s not TD75R, like “X” 20 ForeignID is the only value we’re not looking for.
1 TD75R 5 Val is the only value we’re not looking for.
1 Some value that’s not TD75R, like “X” 5 ForeignID and val have values we’re not looking for.
2 TD75R 20 ID is the only value we’re not looking for.
2 Some value that’s not TD75R, like “X” 20 ID and ForeignID have values we’re not looking for.
2 TD75R 5  ID and Val have values we’re not looking for.
2 Some value that’s not TD75R, like “X” 5  Nothing has the value we’re looking for.

 

And then we’d have to work out the results (always showing our work!) for each scenario.

That’s enough for today. I hope at the very least, you’ve learned how to use truth tables to work out results for complicated clauses!

 

P.S. This is a huge topic, and I can’t even begin to cover it all in one blog post. For one thing, AND/OR/NOT logic applies elsewhere – IF, CASE, JOIN…ON, and so forth. For another, there’s a lot more theory here. Feel free to chime in with more info and more references if you’ve got em!

5 thoughts on “Fix WHERE clause AND/OR/NOT confusion with truth tables

  1. Greg

    Gee, thanks, you reminded me of Modus Ponens which I had to go look back up.

    But yeah, truth tables for the win!

  2. Pingback: The Joys Of Boolean Logic – Curated SQL

  3. Mark Freeman

    Back in the late 80’s I used a great program called Logic Gem that would let me enter all the conditions and the actions for the various combinations. It would flag any permutations that were left unaccounted for, and generate code to implement the table. To give you an idea of the complexity it could handle, I worked in conjunction with tax analysts to model the infamous Form 1040 and most of the schedules using this program to create hundreds of these tables and generate code that we used to validate tax returns for electronic filing.

    It was a very useful program, but sadly long gone. I don’t think there is anything else like it available today.

    https://www.pcorner.com/list/MISC/LGDEMO.ZIP/INFO/
    https://bit.ly/2qOJFlW

  4. Joe Sheldon

    A simple application of De Morgan’s Theorem shows at a glance that the two WHERE clauses aren’t equivalent. The trick is that when you move a NOT in or out of the parenthesis you need to swap the ANDs and ORs. So:

    !(x=1 AND y=’TD75R’) = (x!=1 OR y!=’TD75R’)

  5. BestKory

    I have noticed you don’t monetize your page, don’t waste your traffic, you can earn additional bucks every month because you’ve got hi quality content.
    If you want to know how to make extra money, search
    for: Ercannou’s essential adsense alternative

Comments are closed.