|
|
|
SSC-Enthusiastic
      
Group: General Forum Members
Last Login: Monday, May 20, 2013 2:54 AM
Points: 119,
Visits: 214
|
|
Is no one else going to point out that the results of this process are flawed: the first four values are given as zero, which is just plain wrong! (One could argue that in some cases they should return NULL, but never zero.)
Throw away your pocket calculators; visit www.calcResult.com
|
|
|
|
|
SSCarpal Tunnel
       
Group: General Forum Members
Last Login: 2 days ago @ 1:35 AM
Points: 4,789,
Visits: 1,336
|
|
Very good point pointed out by Mike. It will be never zero.
|
|
|
|
|
SSC-Insane
         
Group: General Forum Members
Last Login: Today @ 4:09 AM
Points: 21,357,
Visits: 9,539
|
|
I've had weirder requests than this... sometimes the user wants the data if and only if a certain amount of days has been taken into account.
But I agree... that looks funny to me too!
|
|
|
|
|
SSC-Insane
         
Group: General Forum Members
Last Login: Today @ 8:19 AM
Points: 21,625,
Visits: 27,471
|
|
I'll address a couple of concerns from my point of view.
1. Based on the article, the first 4 values should be zero. This is why I put an isnull in my code. If you take that out, the first four values will be null.
2. The identity column. Again, based on the article, the sole purpose of the identity column is to provide an order to the values inserted into the table. By making this column a primary key, I also made this a clustered index allowing it to force the order specified. By Jeff's way of doing this, I also should have put an index hint on the update query as well, but for this demonstration it worked well without it. Since the purpose of the identity field was order, if there was a gap it wouldn't have caused an issue.
Some of the other things that have been brought up are actually extensions of this article, and I challenge those individuals to pursue those and show us what you find, either as a post here, or write another article expanding on what the author started.
This is how we learn new tricks and ways to accomplish a variety of tasks.
I reran my queries, once with the initial data set, and a second time with a larger data set. Below are the row counts, statistics io, ans statistics time from the runs.
row count: 20 -- Cross Join Query -- Table 'Accounts'. Scan count 17, logical reads 74, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 2 ms. -- Cross Join Query -- -- Update Query -- Table 'Accounts'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 44 ms. -- Update Join Query -- -- Select After Update Query -- Table 'Accounts'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. -- Select After Update Query --
Row Count: 3280 -- Cross Join Query -- Table 'Accounts'. Scan count 3278, logical reads 6663, physical reads 0, read-ahead reads 49, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 94 ms, elapsed time = 246 ms. -- Cross Join Query -- -- Update Query -- Table 'Accounts'. Scan count 1, logical reads 18, physical reads 0, read-ahead reads 49, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 31 ms, elapsed time = 35 ms. -- Update Join Query -- -- Select After Update Query -- Table 'Accounts'. Scan count 1, logical reads 18, physical reads 0, read-ahead reads 38, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 201 ms. -- Select After Update Query --
 Lynn Pettis
For better assistance in answering your questions, click here For tips to get better help with Performance Problems, click here For Running Totals and its variations, click here or when working with partitioned tables For more about Tally Tables, click here For more about Cross Tabs and Pivots, click here and here Managing Transaction Logs
SQL Musings from the Desert Fountain Valley SQL (My Mirror Blog)
|
|
|
|
|
SSC-Dedicated
           
Group: General Forum Members
Last Login: Today @ 8:14 AM
Points: 32,910,
Visits: 26,802
|
|
Hugo Kornelis (11/27/2008) What I was refering too is the lack of ROW_NUMBER() in SQL Server 2000. This means you'll either have to take your chance with IDENTITY, at the risk of gaps, as the author of this article did; or you have to use a correlated subquery to calculate the row number on the fly, which can result in dramatic performance as the amount of rows grows. Plus, the queries tend to get long and hard to understand.
Nope... in SQL Server 2000, just do a SELECT INTO a temp table with the IDENTITY function and the author's code works just fine without any difficulty for length or understanding.
--Jeff Moden "RBAR is pronounced "ree-bar" and is a "Modenism" for "Row-By-Agonizing-Row".
First step towards the paradigm shift of writing Set Based code: Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column."
For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/
For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
|
|
|
|
|
SSC-Dedicated
           
Group: General Forum Members
Last Login: Today @ 8:14 AM
Points: 32,910,
Visits: 26,802
|
|
Lynn Pettis (11/26/2008) Good article, but let's take another approach and see what we see.
Heh... you beat me to it, again. ;)
--Jeff Moden "RBAR is pronounced "ree-bar" and is a "Modenism" for "Row-By-Agonizing-Row".
First step towards the paradigm shift of writing Set Based code: Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column."
For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/
For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
|
|
|
|
|
SSC-Insane
         
Group: General Forum Members
Last Login: Today @ 8:19 AM
Points: 21,625,
Visits: 27,471
|
|
|
|
|
|
Mr or Mrs. 500
      
Group: General Forum Members
Last Login: Sunday, May 19, 2013 4:00 AM
Points: 533,
Visits: 2,285
|
|
I like both approaches to the problem. They both have a refreshing spark of originality.
I'm not entirely sure if I completely agree with all Hugo's objections, though I share his caution. 'Quirky Update' techniques can go wrong if you are not entirely aware of certain 'gotchas', but they were documented, used, and supported even before Microsoft bought the product. For the 'quirky update' approach that Lynne uses to work safely, you have to remember certain rules (e.g. updates are done in the order of the clustered index, all '@var=col=expression' variable assignments are done before any simple column updates-I hope I've remembered that the right way around!)
Best wishes,
Phil Factor Simple Talk
|
|
|
|
|
SSCertifiable
       
Group: General Forum Members
Last Login: Today @ 3:22 AM
Points: 5,244,
Visits: 7,059
|
|
Lynn Pettis (11/27/2008) Since the purpose of the identity field was order, if there was a gap it wouldn't have caused an issue.
Hi Lynn,
But you are using the IDENTITY values for more than just imposing an order. You use "WHERE B.ID BETWEEN A.ID - 4 AND A.ID" to find the current and four preceeding rows - but if there are gaps, then less than four preceeding rows will match this clause.
Hugo Kornelis, SQL Server MVP Visit my SQL Server blog: http://sqlblog.com/blogs/hugo_kornelis
|
|
|
|
|
SSCertifiable
       
Group: General Forum Members
Last Login: Today @ 3:22 AM
Points: 5,244,
Visits: 7,059
|
|
Jeff Moden (11/27/2008)
Hugo Kornelis (11/27/2008) What I was refering too is the lack of ROW_NUMBER() in SQL Server 2000. This means you'll either have to take your chance with IDENTITY, at the risk of gaps, as the author of this article did; or you have to use a correlated subquery to calculate the row number on the fly, which can result in dramatic performance as the amount of rows grows. Plus, the queries tend to get long and hard to understand.Nope... in SQL Server 2000, just do a SELECT INTO a temp table with the IDENTITY function and the author's code works just fine without any difficulty for length or understanding.
Hi Jeff,
You're right. When using SELECT INTO a temp table with the IDENTITY function (*), then there will not be any gaps and the range of A.ID-4 up to A.ID will always have 5 rows. But unless I overlooked something, this was not in the article. To me, the article appears to imply that any IDENTITY row can be used for this. And since many tables already have an IDENTITY column, often with gaps in the sequence due to deleted data or rolled back inserts, I thought it'd be better to point out this danger.
(*) There is another potential problem here. I know that there is only one situation where Microsoft guarantees that identity values are given out in the expected order when using ORDER BY in an INSERT statement, but I can never recall if this guarantee is for SELECT INTO with the IDENTITY() function, of for INSERT ... SELECT on a table with a predefined IDENTITY column. And I can never find this particular bit of documentation when I need it. I think that SELECT INTO with the IDENTITY() function is the supported scenario, but if you are going to use this in production you'd probably better doublecheck first, for my memory is known to .... aaahh, what was I going to say again? :)
Hugo Kornelis, SQL Server MVP Visit my SQL Server blog: http://sqlblog.com/blogs/hugo_kornelis
|
|
|
|