November 26, 2009 at 1:35 pm
If multiplication happened before division than these would return the same answer, but they dont.
Declare @Salary int
Set @Salary = 85199
Select @Salary/100*115, @Salary/(100*115)
Edit: please note this is not a solution to the problem, the both have wrong answers for the original problem.
November 26, 2009 at 1:57 pm
Agreed. Items like multiplication and division have the same precedence and, provided nothing is include to interfer with the order of precedence (such as parenthesis), are solved left to right as they appear.
--Jeff Moden
Change is inevitable... Change for the better is not.
November 26, 2009 at 2:58 pm
jarred.nicholls (11/26/2009)
Jason Lees-299789 (11/26/2009)
As an aside, one of my colleagues ran some internal tests on a somewhat larger data set (1000 rows, same number of columns) and found that the Cursor ran significantly faster than the last option.Cursors and temp tables are very similar, since a cursor creates a temp table in tempdb (spooling all data to disk before being read back)...just like a temp table does. A cursor has an upfront hit when allocating itself, but that overhead doesn't occur with each row fetch and each row fetch is quite speedy.
The CPU cycles is much greater on each row's operation in the identity temp table method (it is doing a COUNT(*) on the temp table each iteration). With a large data set, a cursor will (always) startup slower but finish faster and with less CPU. On a small data set, a cursor will still startup slower but finish slower as well.
Bottom line is, the last method makes certain assumptions about the identity column that can't always be made and thus isn't a universal solution. And of course, 99% of the time there is a set-based solution that will run circles around any procedural solution. I once tuned a stored procedure that took over 2 hours to complete by replacing a cursor with a set-based solution and brought the execution time down to just around 15 seconds. If you are forced into a procedural situation, first post your situation onto a forum and let someone find a set-based solution to the problem (there's a great chance there is one), and if none is found, use a method that suits the size of the data set. Martin's solution is the appropriate one here, no matter the size of the data set - it doesn't use a temp table.
No Arguments there, in fact i pretty much said that martins was the best non-set based solution, and im not saying that a cursor should be considered and that set based operations are not the best way.
To be honest there was only one situation ive come accross that needed while loop, and never one that needed a cursor in stead of Set based theories.
The issue i had with the article was that the sample data set is miniscule, so it doesnt proove that cursors are worse than loops in real world situations.
_________________________________________________________________________
SSC Guide to Posting and Best Practices
November 26, 2009 at 3:27 pm
Yeah I was just adding on to your statement...I knew you were aware of that, but was just stating to others (in many words) "what your colleague experienced makes sense and the size of the data set can make a difference"
November 26, 2009 at 4:03 pm
What a useless article. It's full of misinformation and bad practice (SELECT TOP 1 id from #temp) won't even work reliably. There is no reason on earth to use any of the methods other than set or cursor, even if they were reliable, which they are not.
Anyone seeking to advance their skills by using anything in this article should be very wary.
November 26, 2009 at 4:21 pm
Please note that id as identity, so using count (*)
do not deliver the last record but much better to use max (id)
.
Besides the set should be:
set salary = salary * 1.15
dividing machines are bad.
November 26, 2009 at 5:34 pm
This article will improve your skills by reading it, then going into the discussion section and learning how the solution provided is wrong, why not use it, and what to use instead.
November 26, 2009 at 6:04 pm
fzaynoun (11/26/2009)
This article will improve your skills by reading it, then going into the discussion section and learning how the solution provided is wrong, why not use it, and what to use instead.
rofl
November 27, 2009 at 8:45 am
I'm sure I will receive much abuse for this post, but I'm going to share my thoughts anyway because I am a big fan of SQLServer Central and I care about the quality, accuracy and relevancy of the content on this site.
That being said, I found this article extremely disappointing on many levels. First off, as has been mentioned already, the operator precedence applied, as well as the corresponding result, are identical for the expressions (X * Y) / Z and X*Y/Z.
Second, as the author mentions, SQL is built upon set theory and the performance of set based operations dramaticaly outperforms sequential operations, which is why I can't understand why the artical is demonstrating alternatives to set-based solutions when a real-world premise for doing so hasn't even been provided.
Last, there are several set-based operations that can accomplish sophisticated updates (like using ROWCOUNT) that numerous prior articles on this very site have identified. So, as I said, I am very disappointed with this article and fail to see how it is relevant (or helpful) at all to SQL programmers new and old.
Am I missing something here?
November 30, 2009 at 10:00 am
"Don't use salary * 115 / 100. This violates the operator precedence rule and gives the wrong result."
That statement is absolutely wrong. The Microsoft page that the article links to says "When two operators in an expression have the same operator precedence level, they are evaluated left to right based on their position in the expression."
Since, as has been mentioned in the comments, multiply and divide have the same precedence, the expression
salary * 115 / 100
is exactly and precisely the same as
(salary * 115)/ 100
Yes, dividing 115 / 100 returns 1, but that doesn't happen here if parentheses are not used. Salary is multiplied by 115 before the result of that is divided by 100. Left to right. (I prefer Salary * 1.15, which someone mentioned above.)
It would be nice to see the original article get corrected by the author!
David Walker
December 1, 2009 at 6:48 pm
Operator precedence isn't just a programming or SQL server concept - it's a basic rule of mathematics. And no, multiplication doesn't occur before division or vice versa. The left-most operation is evaluated first. This is even clearly conveyed in the linked microsoft article.
The reason you may get differences where division is used is not due to operator precedence - it's due to SQL server interpreting the numerator and denominator as integers and therefore defining the result to be an integer, truncating the fractional portion.
The simpliest way to avoid this is to explicitly make either the numerator or denominator a decimal term, ie use / 100.0 instead of just / 100 or explicitly cast either as a decimal type. The result will then also be a decimal type. (Casting the result after the calculation has no effect.)
However, in this particular case, the numerator would already be a decimal type by the time the division occurs - salary is a float so salary * 115 produces a decimal type. So this whole concept doesn't even apply to this example. Furthermore, the reason for not simply using salary * 1.15 eludes me.
It may seem silly to harp on about a minor technicality, but getting such a basic concept wrong invalidates the credibility of the rest of the article. I'd advise a bit more fact checking and testing for next time.
Viewing 11 posts - 16 through 25 (of 25 total)
You must be logged in to reply to this topic. Login to reply