[dba-SQLServer] Confusion Regarding Figure 3-11 in "Murach's SQLServer 2008 for Developers" Book

Michael Maddison michael at ddisolutions.com.au
Mon Oct 3 01:51:05 CDT 2011


Hi Alan,

 

Mixing AND and ORs usually requires () to get right output. Is this not
the purpose of the demonstration :-)

 

>From the help file, precedence -- logical operators

 

SELECT ProductID, ProductModelID

FROM AdventureWorks.Production.Product

WHERE ProductModelID = 20 OR ProductModelID = 21   AND Color = 'Red' 

 

You can change the meaning of the query by adding parentheses to force
evaluation of the OR first. The following query finds only products
under models 20 and 21 that are red.

 

Copy Code 

SELECT ProductID, ProductModelID

FROM AdventureWorks.Production.Product

WHERE (ProductModelID = 20 OR ProductModelID = 21)   AND Color = 'Red'

 

Using parentheses, even when they are not required, can improve the
readability of queries and reduce the chance of making a subtle mistake
because of operator precedence. There is no significant performance
penalty in using parentheses. The following example is more readable
than the original example, although they are syntactically the same.

 

Copy Code 

SELECT ProductID, ProductModelID

FROM AdventureWorks.Production.Product

WHERE ProductModelID = 20 OR (ProductModelID = 21   AND Color = 'Red')

 

Precedence is determined by AND/OR and ()ing, not by where the AND and
OR are in the statement...

HTH

 

Cheers

 

Michael M

 

 

-----Original Message-----
From: dba-sqlserver-bounces at databaseadvisors.com
[mailto:dba-sqlserver-bounces at databaseadvisors.com] On Behalf Of Alan
Lawhon
Sent: Sunday, 2 October 2011 11:05 PM
To: 'Discussion concerning MS SQL Server'
Subject: [dba-SQLServer] Confusion Regarding Figure 3-11 in "Murach's
SQLServer 2008 for Developers" Book

 

I've sent the following email to the folks at Murach books asking a
question about something I've run across in their book on SQL Server
2008.  Since they took about two weeks to respond to my last inquiry, I
thought it would be faster to consult with the experts on this message
board.  (If any of you have a copy of "Murach's SQL Server 2008 for
Developers" book, you can find the two examples I'm referring to on page
104 and 105 of that book.

 

     

 

 

Dear Mike, Joel, and Bryan:

 

 

Hello, it's me again - Alan C. Lawhon of Huntsville, Alabama.  I'm
reading the section of chapter 3 on "How to use the AND, OR, and NOT
logical operators" and specifically two of the examples from Figure
3-11.  The two examples I'm referring to deal with compound conditions
[in WHERE clauses] and how using parenthesis alters the order of
precedence.  I've come across something which does not make sense which
I'm hoping you guys can explain.

Based on the two examples given on page 105, I constructed (and
executed) the following query.

 

 

USE AP

 

GO

 

SELECT InVoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal,
CreditTotal,

 

  (InvoiceTotal - PaymentTotal - CreditTotal) AS [BalanceDue]

 

FROM Invoices

 

--

 

--  The following WHERE clause (with no parenthesis) returns 100 rows.
(I have

 

--  deliberately commented out this WHERE clause after running and
testing

 

--  it.  Execution of this WHERE clause produced a 100 row resultset
just

 

--  as the fifth example on page 105 indicates it should.)

 

--

 

-- WHERE InvoiceDate > '05-01-2008' OR InvoiceTotal > 500 

 

--   AND InvoiceTotal - PaymentTotal - CreditTotal > 0

 

--

 

--  The above WHERE clause is very confusing as I don't understand why
the

 

--  [BalanceDue] calculation in the AND condition portion of the WHERE

 

--  clause produces 89 records in the resultset where the calculated
value

 

--  in the [BalanceDue] field is equal to 0.00?  Those 89 records should
be

 

--  excluded, shouldn't they?  (They are excluded in the alternate WHERE

 

--  clause [below] which returns 11 rows and the value in the
[BalanceDue]

 

--  calculated field is greater than 0.00 for all eleven of those
records.)

 

--

 

--  Rewritten WHERE clause (using parenthesis to change order of
precedence)

 

--  returns 11 rows - just as Figure 3-11 indicates it should.

 

--

 

WHERE (InvoiceDate > '05-01-2008' OR InvoiceTotal > 500)

 

  AND InvoiceTotal - PaymentTotal - CreditTotal > 0

 

--

 

--  This WHERE clause makes sense!

 

--

 

ORDER BY [BalanceDue] DESC

 

 

OK, here's where I'm confused.  It's the condition following the "AND"

qualifier in both versions of the WHERE clause.  It seems to me that in
the first [commented out] WHERE clause, 89 of those 100 rows should not
have been returned!  Specifically, the 89 rows where the [BalanceDue]
calculated field, (i.e. "InvoiceTotal - PaymentTotal - CreditTotal >
0"), evaluated to 0.00.  Those rows should not have been returned
because the logical "AND"

condition does not evaluate to true.  (Interestingly, in the second
WHERE clause, where parenthesis is used to change the order of
precedence, only 11 rows are returned - which agrees with what Figure
3-11 indicates.)  In the second WHERE clause example, it appears that
the SQL Server database engine (or query processor) correctly evaluates
the "InvoiceTotal - PaymentTotal - CreditTotal > 0" expression and
excludes the 89 rows which do not meet that criteria.  Since the
expression following the "AND" qualifier is identical in both WHERE
clauses, (and the logical expressions on both sides of an "AND"
qualifier have to evaluate to "True" for a row to be returned), I don't
think the 89 records (where the [BalanceDue] field shows a value of

0.00) should have been returned in the first WHERE clause example.
However, it appears that the SQL Server query processor disagrees with
me since it returned those 89 records!

 

 

I've looked at this repeatedly and it doesn't make sense.  The logical
condition to the right of the AND portion of the first WHERE clause
fails for 89 of the rows returned.  Irrespective of whether or not
parenthesis was used (in that first WHERE clause example), those 89 rows
where the [BalanceDue] field evaluated to 0.00 should not have been
included.  That is my contention, but I must be seriously confused about
this since the query processor says those 89 rows should have been
returned - along with the other 11 rows where "InvoiceTotal -
PaymentTotal - CreditTotal > 0"

evaluated to "True".

 

 

If you guys can help straighten me out (or "unconfuse" me on this), I
will be very grateful.

 

 

Sincerely,

 

 

Alan C. Lawhon

 

Huntsville, Alabama

 

 

_______________________________________________

dba-SQLServer mailing list

dba-SQLServer at databaseadvisors.com
<mailto:dba-SQLServer at databaseadvisors.com> 

http://databaseadvisors.com/mailman/listinfo/dba-sqlserver
<http://databaseadvisors.com/mailman/listinfo/dba-sqlserver> 

http://www.databaseadvisors.com <http://www.databaseadvisors.com> 

 

 

-----

No virus found in this message.

Checked by AVG - www.avg.com <http://www.avg.com> 

Version: 10.0.1410 / Virus Database: 1520/3934 - Release Date: 10/02/11



More information about the dba-SQLServer mailing list