<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>Randomness</title><link>http://blogs.acceleration.net/ryan/category/18.aspx</link><description>Randomness</description><managingEditor>Ryan</managingEditor><dc:language>en-US</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>Ryan</dc:creator><title>Getting a randomish sample with SQL Server 2000</title><link>http://blogs.acceleration.net/ryan/archive/2006/02/09/2820.aspx</link><pubDate>Thu, 09 Feb 2006 19:10:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2006/02/09/2820.aspx</guid><description>&lt;p&gt;
				  I was recently presented with a seemingly simple task, write a query to return a random&lt;span style="color:blue;" title="for some values of random"&gt;*&lt;/span&gt; sample of rows
				  from a table, with the number of rows to pull determined at runtime.  
				  The surrounding problem is a bit more complex, but this was the specific task I was trying to accomplish,
				  and SQL Server 2000 didn't make it very easy.  The rest of my task involved deleting rows where the id wasn't in my random sample.
				&lt;/p&gt;
				&lt;h4&gt;First try, my almost-dream syntax&lt;/h4&gt;
				&lt;p&gt;My first attempt was a bit naive:
				&lt;/p&gt;&lt;div&gt;
&lt;table class="dp-sql" border="0" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;TOP&lt;/span&gt;&lt;span&gt; @limit Id &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; Items &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;ORDER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;BY&lt;/span&gt;&lt;span&gt; NEWID() &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				&lt;/div&gt;
				&lt;code&gt;@limit&lt;/code&gt; is a variable which has how many rows I should be returning.
				I order by NEWID(), which makes a GUID for every row, as this is the best way I know of to get it ordered randomly.  I don't
				think its a terribly good way, but its the best I know.  If you have a better way, please comment or email.
			 
				&lt;p&gt;
				  That snippet will of course fail, giving this error message:
				&lt;/p&gt;&lt;div&gt;Incorrect syntax near '@limit'.&lt;/div&gt;
				Ok, so I can't dynamically set the TOP.  Fine.
			 
				&lt;h4&gt;Use ROWCOUNT&lt;/h4&gt;
				&lt;p&gt;
				  By using SET ROWCOUNT @limit, I could instruct SQL Server to only return @limit rows when performing a SELECT.  So, this was the query to 
				  delete rows not in my random sample:
				  &lt;/p&gt;&lt;div&gt;
&lt;table class="dp-sql" border="0" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="comment"&gt;--limit results to @limit rows&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SET&lt;/span&gt;&lt;span&gt; ROWCOUNT @limit &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;DELETE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;WHERE&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="op"&gt;NOT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="op"&gt;IN&lt;/span&gt;&lt;span&gt;( &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;    &lt;span class="comment"&gt;--due to rowcount, this should be my random sample of @limit Ids&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;    &lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; Items &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;    &lt;span class="keyword"&gt;ORDER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;BY&lt;/span&gt;&lt;span&gt; NEWID() &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;    ) &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--clear the rowcount, so results aren't limited&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SET&lt;/span&gt;&lt;span&gt; ROWCOUNT 0 &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				  &lt;/div&gt;
					That snippet also fails, giving this error:
				&lt;div class="Code"&gt;The ORDER BY clause is invalid in views, inline functions, derived tables, and subqueries, unless TOP is also specified.&lt;/div&gt;
				Ok, so I can't use ORDER BY in the subquery.  Well damn, that would have been really clean.  I could add a &lt;code&gt;TOP 2147483647&lt;/code&gt; in there, but that seemed like a bad idea.
				
				&lt;h4&gt;Use a table variable&lt;/h4&gt;
				&lt;p&gt;
				  Ok, next thought is to use a table variable, insert my rows in a random order, numbering each row, and then pull the rows with a number
				  below my limit:
				&lt;/p&gt;&lt;div&gt;
&lt;table class="dp-sql" border="0" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="comment"&gt;--make the table variable, the num column will count upwards as we insert, numbering the rows&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;DECLARE&lt;/span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;TABLE&lt;/span&gt;&lt;span&gt; (id &lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="op"&gt;NOT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="op"&gt;NULL&lt;/span&gt;&lt;span&gt;, num &lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="op"&gt;NOT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="op"&gt;NULL&lt;/span&gt;&lt;span&gt; IDENTITY(1,1)) &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--insert into the table in random order&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;INSERT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;INTO&lt;/span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; (id) &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;(&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id  &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; Items &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;ORDER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;BY&lt;/span&gt;&lt;span&gt; NEWID()) &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--get out our sample&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;WHERE&lt;/span&gt;&lt;span&gt; num &amp;lt;= @limit &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				&lt;/div&gt;
				That snippet also fails, giving this error:
				&lt;div class="Code"&gt;Incorrect syntax near the keyword 'ORDER'.&lt;/div&gt;
				Oh right, I can't use ORDER BY in the subquery.  Fine.
				
				&lt;h4&gt;Use a temporary table and INSERT INTO&lt;/h4&gt;
				&lt;p&gt;
				  I was trying to avoid temporary tables, since they have some performance issues, but figured maybe there wasn't any other way.  So,
				  I broke down and used a temp table:
				  &lt;/p&gt;&lt;div&gt;
				  &lt;table class="dp-sql" border="0" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="comment"&gt;--select into the temp table, using IDENTITY to get my row counter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id, IDENTITY(&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;, 1,1) [num] &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;INTO&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; Items &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;ORDER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;BY&lt;/span&gt;&lt;span&gt; NEWID() &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--get out our sample&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;WHERE&lt;/span&gt;&lt;span&gt; num &amp;lt; @limit &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--clean up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;DROP&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;TABLE&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				  &lt;/div&gt;
				That snippet also fails, giving this error:
				&lt;div class="Code"&gt;Cannot add identity column, using the SELECT INTO statement, to table '#temp', which already has column 'Id' that inherits the identity property.&lt;/div&gt;
				Ok... So the 'identity' property gets inherited into the temp table, and so I can't specify another identity column.  
				I did some searching in the docs, and there didn't seem to be a way to get an autoincrement field without it
				being an identity field.  Ok, fine, I know a retarded way to get around that.
				
				&lt;h4&gt;Use a temporary table, INSERT INTO, and a table variable to mask the identity column&lt;/h4&gt;
				&lt;p&gt;
				  I actually wrote a variant of this:
				  &lt;/p&gt;&lt;div&gt;
				  &lt;table class="dp-sql" border="0" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="comment"&gt;--Make a table to copy my ids into&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;DECLARE&lt;/span&gt;&lt;span&gt; @retarded &lt;/span&gt;&lt;span class="keyword"&gt;TABLE&lt;/span&gt;&lt;span&gt; (id &lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--copy all my ids in, but leave the 'identity' property behind&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;INSERT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;INTO&lt;/span&gt;&lt;span&gt; @retarded (id) &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;    (&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; Items) &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--select into the temp table, using IDENTITY to get my row counter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id, IDENTITY(&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;, 1,1) [num] &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;INTO&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; @retarded &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;ORDER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;BY&lt;/span&gt;&lt;span&gt; NEWID() &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--get out our sample&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;WHERE&lt;/span&gt;&lt;span&gt; num &amp;lt; @limit &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--clean up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;DROP&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;TABLE&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				  &lt;/div&gt;
				  This worked, but made me sick to my stomach.  There &lt;em&gt;had&lt;/em&gt; to be a better way.
				
				&lt;h4&gt;Use a temporary table, INSERT INTO, and a dummy expression&lt;/h4&gt;
				&lt;p&gt;
				  So, I dug through some more documentation, finding this gem:
				  &lt;/p&gt;&lt;blockquote&gt;
				  When an existing identity column is selected into a new table, the new column inherits the IDENTITY property, unless one of the following conditions is true: 
				  &lt;ul&gt;
					 &lt;li&gt;The SELECT statement contains a join, GROUP BY clause, or aggregate function.&lt;/li&gt;
					 &lt;li&gt;Multiple SELECT statements are joined by using UNION.&lt;/li&gt;
					 &lt;li&gt;The identity column is listed more than one time in the select list.&lt;/li&gt;
					 &lt;li&gt;The identity column is part of an expression.&lt;/li&gt;
				  &lt;/ul&gt;
				  If any one of these conditions is true, the column is created NOT NULL instead of inheriting the IDENTITY property. All rules and restrictions for the identity columns apply to the new table.
				&lt;/blockquote&gt;
				Ok, so I decided the least despicable thing to do would be to make a dummy expression to drop the identity property:
				&lt;div class="Code"&gt;
&lt;table class="dp-sql" border="0" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="comment"&gt;--select into the temp table, using IDENTITY to get my row counter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id*1 [Id], IDENTITY(&lt;/span&gt;&lt;span class="keyword"&gt;int&lt;/span&gt;&lt;span&gt;, 1,1) [num] &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;INTO&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; Items &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;ORDER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;BY&lt;/span&gt;&lt;span&gt; NEWID() &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--get out our sample&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;SELECT&lt;/span&gt;&lt;span&gt; Id &lt;/span&gt;&lt;span class="keyword"&gt;FROM&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;WHERE&lt;/span&gt;&lt;span&gt; num &amp;lt; @limit &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="comment"&gt;--clean up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="line"&gt;&lt;span class="keyword"&gt;DROP&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span class="keyword"&gt;TABLE&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span class="keyword"&gt;temp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
				  &lt;/div&gt;
				I did some profiling, and doing &lt;code&gt;id*1&lt;/code&gt; was the same as doing &lt;code&gt;id+0&lt;/code&gt;, so I left it as multiplication.
				  
				&lt;p&gt;
				  All in all, very, very frustrating, and I'm not sure if the &lt;code&gt;TOP 2147483647&lt;/code&gt; option above is worse than the hack at the end.  Votes are welcome.&lt;br /&gt;&lt;br /&gt;

				  I hate how much I jump through hoops and reinvent to do what should be very simple tasks.  
				  I mean, c'mon, we've been programming for over 50 years now, and I'm pretty sure pulling a random sample from a dataset is
				  not a new task.  We should be better than this.
				&lt;/p&gt;&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/2820.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p>
				  I was recently presented with a seemingly simple task, write a query to return a random<span style="color:blue;" title="for some values of random">*</span> sample of rows
				  from a table, with the number of rows to pull determined at runtime.  
				  The surrounding problem is a bit more complex, but this was the specific task I was trying to accomplish,
				  and SQL Server 2000 didn't make it very easy.  The rest of my task involved deleting rows where the id wasn't in my random sample.
				</p>
				<h4>First try, my almost-dream syntax</h4>
				<p>My first attempt was a bit naive:
				</p><div>
<table class="dp-sql" border="0" cellpadding="0" cellspacing="0"><tbody><tr></tr><tr><td class="line"><span></span><span class="keyword">SELECT</span><span> </span><span class="keyword">TOP</span><span> @limit Id </span></td></tr><tr><td class="line"><span class="keyword">FROM</span><span> Items </span></td></tr><tr><td class="line"><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> NEWID() </span></td></tr></tbody></table>
				</div>
				<code>@limit</code> is a variable which has how many rows I should be returning.
				I order by NEWID(), which makes a GUID for every row, as this is the best way I know of to get it ordered randomly.  I don't
				think its a terribly good way, but its the best I know.  If you have a better way, please comment or email.
			 
				<p>
				  That snippet will of course fail, giving this error message:
				</p><div>Incorrect syntax near '@limit'.</div>
				Ok, so I can't dynamically set the TOP.  Fine.
			 
				<h4>Use ROWCOUNT</h4>
				<p>
				  By using SET ROWCOUNT @limit, I could instruct SQL Server to only return @limit rows when performing a SELECT.  So, this was the query to 
				  delete rows not in my random sample:
				  </p><div>
<table class="dp-sql" border="0" cellpadding="0" cellspacing="0"><tbody><tr></tr><tr><td class="line"><span></span><span class="comment">--limit results to @limit rows</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SET</span><span> ROWCOUNT @limit </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="keyword">DELETE</span><span> </span><span class="keyword">FROM</span><span> #</span><span class="keyword">temp</span><span> </span><span class="keyword">WHERE</span><span> Id </span><span class="op">NOT</span><span> </span><span class="op">IN</span><span>( </span></td></tr><tr><td class="line">    <span class="comment">--due to rowcount, this should be my random sample of @limit Ids</span><span> </span></td></tr><tr><td class="line">    <span class="keyword">SELECT</span><span> Id </span><span class="keyword">FROM</span><span> Items </span></td></tr><tr><td class="line">    <span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> NEWID() </span></td></tr><tr><td class="line">    ) </td></tr><tr><td class="line"><span class="comment">--clear the rowcount, so results aren't limited</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SET</span><span> ROWCOUNT 0 </span></td></tr></tbody></table>
				  </div>
					That snippet also fails, giving this error:
				<div class="Code">The ORDER BY clause is invalid in views, inline functions, derived tables, and subqueries, unless TOP is also specified.</div>
				Ok, so I can't use ORDER BY in the subquery.  Well damn, that would have been really clean.  I could add a <code>TOP 2147483647</code> in there, but that seemed like a bad idea.
				
				<h4>Use a table variable</h4>
				<p>
				  Ok, next thought is to use a table variable, insert my rows in a random order, numbering each row, and then pull the rows with a number
				  below my limit:
				</p><div>
<table class="dp-sql" border="0" cellpadding="0" cellspacing="0"><tbody><tr></tr><tr><td class="line"><span></span><span class="comment">--make the table variable, the num column will count upwards as we insert, numbering the rows</span><span> </span></td></tr><tr><td class="line"><span class="keyword">DECLARE</span><span> @</span><span class="keyword">temp</span><span> </span><span class="keyword">TABLE</span><span> (id </span><span class="keyword">int</span><span> </span><span class="op">NOT</span><span> </span><span class="op">NULL</span><span>, num </span><span class="keyword">int</span><span> </span><span class="op">NOT</span><span> </span><span class="op">NULL</span><span> IDENTITY(1,1)) </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--insert into the table in random order</span><span> </span></td></tr><tr><td class="line"><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> @</span><span class="keyword">temp</span><span> (id) </span></td></tr><tr><td class="line">(<span class="keyword">SELECT</span><span> Id  </span></td></tr><tr><td class="line"><span class="keyword">FROM</span><span> Items </span></td></tr><tr><td class="line"><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> NEWID()) </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--get out our sample</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id </span><span class="keyword">FROM</span><span> @</span><span class="keyword">temp</span><span> </span><span class="keyword">WHERE</span><span> num &lt;= @limit </span></td></tr></tbody></table>
				</div>
				That snippet also fails, giving this error:
				<div class="Code">Incorrect syntax near the keyword 'ORDER'.</div>
				Oh right, I can't use ORDER BY in the subquery.  Fine.
				
				<h4>Use a temporary table and INSERT INTO</h4>
				<p>
				  I was trying to avoid temporary tables, since they have some performance issues, but figured maybe there wasn't any other way.  So,
				  I broke down and used a temp table:
				  </p><div>
				  <table class="dp-sql" border="0" cellpadding="0" cellspacing="0"><tbody><tr></tr><tr><td class="line"><span></span><span class="comment">--select into the temp table, using IDENTITY to get my row counter</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id, IDENTITY(</span><span class="keyword">int</span><span>, 1,1) [num] </span></td></tr><tr><td class="line"><span class="keyword">INTO</span><span> #</span><span class="keyword">temp</span><span>  </span></td></tr><tr><td class="line"><span class="keyword">FROM</span><span> Items </span></td></tr><tr><td class="line"><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> NEWID() </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--get out our sample</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id </span><span class="keyword">FROM</span><span> #</span><span class="keyword">temp</span><span> </span><span class="keyword">WHERE</span><span> num &lt; @limit </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--clean up</span><span> </span></td></tr><tr><td class="line"><span class="keyword">DROP</span><span> </span><span class="keyword">TABLE</span><span> #</span><span class="keyword">temp</span><span> </span></td></tr></tbody></table>
				  </div>
				That snippet also fails, giving this error:
				<div class="Code">Cannot add identity column, using the SELECT INTO statement, to table '#temp', which already has column 'Id' that inherits the identity property.</div>
				Ok... So the 'identity' property gets inherited into the temp table, and so I can't specify another identity column.  
				I did some searching in the docs, and there didn't seem to be a way to get an autoincrement field without it
				being an identity field.  Ok, fine, I know a retarded way to get around that.
				
				<h4>Use a temporary table, INSERT INTO, and a table variable to mask the identity column</h4>
				<p>
				  I actually wrote a variant of this:
				  </p><div>
				  <table class="dp-sql" border="0" cellpadding="0" cellspacing="0"><tbody><tr></tr><tr><td class="line"><span></span><span class="comment">--Make a table to copy my ids into</span><span> </span></td></tr><tr><td class="line"><span class="keyword">DECLARE</span><span> @retarded </span><span class="keyword">TABLE</span><span> (id </span><span class="keyword">int</span><span>) </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--copy all my ids in, but leave the 'identity' property behind</span><span> </span></td></tr><tr><td class="line"><span class="keyword">INSERT</span><span> </span><span class="keyword">INTO</span><span> @retarded (id) </span></td></tr><tr><td class="line">    (<span class="keyword">SELECT</span><span> Id </span><span class="keyword">FROM</span><span> Items) </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--select into the temp table, using IDENTITY to get my row counter</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id, IDENTITY(</span><span class="keyword">int</span><span>, 1,1) [num] </span></td></tr><tr><td class="line"><span class="keyword">INTO</span><span> #</span><span class="keyword">temp</span><span>  </span></td></tr><tr><td class="line"><span class="keyword">FROM</span><span> @retarded </span></td></tr><tr><td class="line"><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> NEWID() </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--get out our sample</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id </span><span class="keyword">FROM</span><span> #</span><span class="keyword">temp</span><span> </span><span class="keyword">WHERE</span><span> num &lt; @limit </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--clean up</span><span> </span></td></tr><tr><td class="line"><span class="keyword">DROP</span><span> </span><span class="keyword">TABLE</span><span> #</span><span class="keyword">temp</span><span> </span></td></tr></tbody></table>
				  </div>
				  This worked, but made me sick to my stomach.  There <em>had</em> to be a better way.
				
				<h4>Use a temporary table, INSERT INTO, and a dummy expression</h4>
				<p>
				  So, I dug through some more documentation, finding this gem:
				  </p><blockquote>
				  When an existing identity column is selected into a new table, the new column inherits the IDENTITY property, unless one of the following conditions is true: 
				  <ul>
					 <li>The SELECT statement contains a join, GROUP BY clause, or aggregate function.</li>
					 <li>Multiple SELECT statements are joined by using UNION.</li>
					 <li>The identity column is listed more than one time in the select list.</li>
					 <li>The identity column is part of an expression.</li>
				  </ul>
				  If any one of these conditions is true, the column is created NOT NULL instead of inheriting the IDENTITY property. All rules and restrictions for the identity columns apply to the new table.
				</blockquote>
				Ok, so I decided the least despicable thing to do would be to make a dummy expression to drop the identity property:
				<div class="Code">
<table class="dp-sql" border="0" cellpadding="0" cellspacing="0"><tbody><tr></tr><tr><td class="line"><span></span><span class="comment">--select into the temp table, using IDENTITY to get my row counter</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id*1 [Id], IDENTITY(</span><span class="keyword">int</span><span>, 1,1) [num] </span></td></tr><tr><td class="line"><span class="keyword">INTO</span><span> #</span><span class="keyword">temp</span><span>  </span></td></tr><tr><td class="line"><span class="keyword">FROM</span><span> Items </span></td></tr><tr><td class="line"><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> NEWID() </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--get out our sample</span><span> </span></td></tr><tr><td class="line"><span class="keyword">SELECT</span><span> Id </span><span class="keyword">FROM</span><span> #</span><span class="keyword">temp</span><span> </span><span class="keyword">WHERE</span><span> num &lt; @limit </span></td></tr><tr><td class="line"> </td></tr><tr><td class="line"><span class="comment">--clean up</span><span> </span></td></tr><tr><td class="line"><span class="keyword">DROP</span><span> </span><span class="keyword">TABLE</span><span> #</span><span class="keyword">temp</span><span> </span></td></tr></tbody></table>
				  </div>
				I did some profiling, and doing <code>id*1</code> was the same as doing <code>id+0</code>, so I left it as multiplication.
				  
				<p>
				  All in all, very, very frustrating, and I'm not sure if the <code>TOP 2147483647</code> option above is worse than the hack at the end.  Votes are welcome.<br /><br />

				  I hate how much I jump through hoops and reinvent to do what should be very simple tasks.  
				  I mean, c'mon, we've been programming for over 50 years now, and I'm pretty sure pulling a random sample from a dataset is
				  not a new task.  We should be better than this.
				</p><img src ="http://blogs.acceleration.net/ryan/aggbug/2820.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>Crystal Reports 9 Database login prompt</title><link>http://blogs.acceleration.net/ryan/archive/2005/12/15/2809.aspx</link><pubDate>Thu, 15 Dec 2005 13:20:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2005/12/15/2809.aspx</guid><description>&lt;p&gt;
				  One client of mine uses Crystal Reports for reporting, and our experience has been pretty bad overall.  Part of 
				  that might be due to the guy my client hired to create all of them.  He seemed like a nice enough guy, but suffice
				  to say when I was asked to start replacing the Crystal Reports in our existing system there was talk of lawsuits.  Every 
				  report was made using the design view, and they had a funky web interface with really bad UI displaying all the reports.
				&lt;/p&gt;
				&lt;p&gt;
				  Anyway, we had SQL Server replication set up, and then the Crystal Reports were looking at a seperate database server, as
				  they were designed in such a way to be enormously inefficient.  So, when replication decided to crap itself, we switched over
				  to log shipping, thinking everything would just keep working.  One of the many problems that cropped up was the appearance 
				  of a database login prompt:
				&lt;/p&gt;
				&lt;div align="center"&gt;
				  &lt;img src="http://birdman.acceleration.net/ryan/crystal_prompt.png" /&gt;
				&lt;/div&gt;
				&lt;p&gt;
				  We tried changing the connection information in the Crystal designer, and the Crystal designer would always pull up a report just fine.
				  The damn web interface would always prompt for information.  We'd put in the information we entered in the designer, and then
				  it would work.  Since we didn't want to have users entering a user/pass every time they wanted to see a report, we kept changing
				  things, trying to find something that would work.  Finally we found that it would work if we pointed the report at our live database
				  server, and ignore the backup we made for Crystal to use.  As a temporary solution, we started changing all the reports to look
				  at the other server, and googled like mad to try to find a solution.
				&lt;/p&gt;
				&lt;p&gt;
				  After finding many, many people having this problem unresolved, and many, many solutions that are applicable if you're coding these
				  up by hand, but nothing for our problem.  We could tell that it was using the wrong config information, but had no idea how to 
				  change what it was using.
				&lt;/p&gt;
				&lt;h2&gt;Solution&lt;/h2&gt;
				&lt;p&gt;
				  The solution came after Chris did a text search on the web server, and found some random ASP file where the user info was stored:
				&lt;/p&gt;
				&lt;div class="code"&gt;
				  %webroot%\ASP\rPortfolio\HTMLViewers\interactiveViewer.asp
				&lt;/div&gt;
				&lt;p&gt;
				  The username and password for the web interface was hardcoded there, and we couldn't find anything in Crystal that could change it.  
				  Notepad worked just fine.  So, I guess for the web viewer, Crystal silently ignores the settings in the individual reports, and just
				  uses that one.  Great design.
				&lt;/p&gt;&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/2809.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p>
				  One client of mine uses Crystal Reports for reporting, and our experience has been pretty bad overall.  Part of 
				  that might be due to the guy my client hired to create all of them.  He seemed like a nice enough guy, but suffice
				  to say when I was asked to start replacing the Crystal Reports in our existing system there was talk of lawsuits.  Every 
				  report was made using the design view, and they had a funky web interface with really bad UI displaying all the reports.
				</p>
				<p>
				  Anyway, we had SQL Server replication set up, and then the Crystal Reports were looking at a seperate database server, as
				  they were designed in such a way to be enormously inefficient.  So, when replication decided to crap itself, we switched over
				  to log shipping, thinking everything would just keep working.  One of the many problems that cropped up was the appearance 
				  of a database login prompt:
				</p>
				<div align="center">
				  <img src="http://birdman.acceleration.net/ryan/crystal_prompt.png" />
				</div>
				<p>
				  We tried changing the connection information in the Crystal designer, and the Crystal designer would always pull up a report just fine.
				  The damn web interface would always prompt for information.  We'd put in the information we entered in the designer, and then
				  it would work.  Since we didn't want to have users entering a user/pass every time they wanted to see a report, we kept changing
				  things, trying to find something that would work.  Finally we found that it would work if we pointed the report at our live database
				  server, and ignore the backup we made for Crystal to use.  As a temporary solution, we started changing all the reports to look
				  at the other server, and googled like mad to try to find a solution.
				</p>
				<p>
				  After finding many, many people having this problem unresolved, and many, many solutions that are applicable if you're coding these
				  up by hand, but nothing for our problem.  We could tell that it was using the wrong config information, but had no idea how to 
				  change what it was using.
				</p>
				<h2>Solution</h2>
				<p>
				  The solution came after Chris did a text search on the web server, and found some random ASP file where the user info was stored:
				</p>
				<div class="code">
				  %webroot%\ASP\rPortfolio\HTMLViewers\interactiveViewer.asp
				</div>
				<p>
				  The username and password for the web interface was hardcoded there, and we couldn't find anything in Crystal that could change it.  
				  Notepad worked just fine.  So, I guess for the web viewer, Crystal silently ignores the settings in the individual reports, and just
				  uses that one.  Great design.
				</p><img src ="http://blogs.acceleration.net/ryan/aggbug/2809.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>new favorite acronym</title><link>http://blogs.acceleration.net/ryan/archive/2005/10/05/2783.aspx</link><pubDate>Wed, 05 Oct 2005 15:13:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2005/10/05/2783.aspx</guid><description>WTFAYMTAAAT:&lt;br /&gt;
&lt;blockquote&gt;
What The Fuck, Are You Mental, There Already Are A Thousand
&lt;/blockquote&gt;
I saw this applied to RSS Aggregators.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/2783.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">WTFAYMTAAAT:<br />
<blockquote>
What The Fuck, Are You Mental, There Already Are A Thousand
</blockquote>
I saw this applied to RSS Aggregators.<img src ="http://blogs.acceleration.net/ryan/aggbug/2783.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>Theoden picking up the slack.</title><link>http://blogs.acceleration.net/ryan/archive/2005/03/04/699.aspx</link><pubDate>Fri, 04 Mar 2005 13:51:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2005/03/04/699.aspx</guid><description>Now my brother &lt;a href="http://molecularbear.com/blog/"&gt;Theoden&lt;/a&gt; has decided to pick up the torch and dispense his own tips.  His &lt;a href="http://www.molecularbear.com/blog/archives/2005/02/tip_1_all_funct.html"&gt;first tip&lt;/a&gt; describes the brilliant &lt;code&gt;LEN&lt;/code&gt; function in SQL Server.  &lt;br /&gt;&lt;br /&gt;
Try &lt;code&gt;SELECT LEN('1234 ')&lt;/code&gt; to see what he means.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/699.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">Now my brother <a href="http://molecularbear.com/blog/">Theoden</a> has decided to pick up the torch and dispense his own tips.  His <a href="http://www.molecularbear.com/blog/archives/2005/02/tip_1_all_funct.html">first tip</a> describes the brilliant <code>LEN</code> function in SQL Server.  <br /><br />
Try <code>SELECT LEN('1234 ')</code> to see what he means.<img src ="http://blogs.acceleration.net/ryan/aggbug/699.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>Supers Bowl XXXIV</title><link>http://blogs.acceleration.net/ryan/archive/2005/02/02/606.aspx</link><pubDate>Wed, 02 Feb 2005 15:15:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2005/02/02/606.aspx</guid><description>The party is officially &lt;a href="http://blogs.acceleration.net/ryan/articles/604.aspx"&gt;on&lt;/a&gt;.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/606.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">The party is officially <a href="http://blogs.acceleration.net/ryan/articles/604.aspx">on</a>.<img src ="http://blogs.acceleration.net/ryan/aggbug/606.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>Super Bowl XXXIV</title><link>http://blogs.acceleration.net/ryan/archive/2005/01/23/562.aspx</link><pubDate>Sun, 23 Jan 2005 19:17:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2005/01/23/562.aspx</guid><description>It's about time for another party.  I'm moving into a new place soon, and we are going to have a traditional beer/food/football
   party.  We're going to have the following extravagent items:
   &lt;ul&gt;
     &lt;li&gt;Beer&lt;/li&gt;
     &lt;li&gt;Hoff is borrowing a meat smoker, through which there will be much smoking of meat.&lt;/li&gt;
     &lt;li&gt;I'm making penalty flags, and those will be thrown about in drunken rage.&lt;/li&gt;
     &lt;li&gt;Cox has no fucking HD Fox station, so we can't see it HD, but there will still be the ungodly 52" television.&lt;/li&gt;
   &lt;/ul&gt;
   So, I'm not exactly sure where this party will be, but I'll update once I know where I'm living.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/562.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">It's about time for another party.  I'm moving into a new place soon, and we are going to have a traditional beer/food/football
   party.  We're going to have the following extravagent items:
   <ul>
     <li>Beer</li>
     <li>Hoff is borrowing a meat smoker, through which there will be much smoking of meat.</li>
     <li>I'm making penalty flags, and those will be thrown about in drunken rage.</li>
     <li>Cox has no fucking HD Fox station, so we can't see it HD, but there will still be the ungodly 52" television.</li>
   </ul>
   So, I'm not exactly sure where this party will be, but I'll update once I know where I'm living.<img src ="http://blogs.acceleration.net/ryan/aggbug/562.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>arms race</title><link>http://blogs.acceleration.net/ryan/archive/2005/01/14/490.aspx</link><pubDate>Fri, 14 Jan 2005 12:16:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2005/01/14/490.aspx</guid><description>As we get more traffic, we've also been getting some comment spam, and apparently 
&lt;a href="http://dotnetworkaholics.com/blog/archive/2005/01/14/248.aspx"&gt;Paul Lockwood&lt;/a&gt; is as well.
We've had a few ideas between &lt;a title="Nathan's blog" href="http://blogs.acceleration.net/birdman/"&gt;Nathan&lt;/a&gt;, &lt;a title="Russ' blog" href="http://blogs.acceleration.net/Russ/"&gt;Russ&lt;/a&gt;, and I of how to stop it, but haven't 
gotten around to implementing any of them.
&lt;br /&gt;&lt;br /&gt;
Assuming the spammers make comments by just submitting HTTP requests from a perl script or something, 
we thought of a relatively easy fix.  Add some new hidden fields, and have the server read from those hidden fields, 
and then have some javascript to copy content from the existing text fields to the hidden fields onsumbit.  The only 
hassle there is is the spammers learn what the hidden field names are, and adjust their perl scripts.  To combat
that we'd have to dynamically generate hidden field names, which could be tossed in viewstate without too much fuss.
Then the spammers would have to do web crawling, instantiating and controlling a browser so they could get the names
right.
&lt;br /&gt;&lt;br /&gt;
One bad thought we had was to integrate &lt;a href="http://spambayes.sourceforge.net/"&gt;SpamBayes&lt;/a&gt;, the excellent, 
excellent spam filter that you should really be running if you use Outlook.  Seed SpamBayes with good comments, then have 
it show/hide comments according to its statistics.  Then there would need to be a section in the admin for you to 
train the thing, but its certainly doable.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/490.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">As we get more traffic, we've also been getting some comment spam, and apparently 
<a href="http://dotnetworkaholics.com/blog/archive/2005/01/14/248.aspx">Paul Lockwood</a> is as well.
We've had a few ideas between <a title="Nathan's blog" href="http://blogs.acceleration.net/birdman/">Nathan</a>, <a title="Russ' blog" href="http://blogs.acceleration.net/Russ/">Russ</a>, and I of how to stop it, but haven't 
gotten around to implementing any of them.
<br /><br />
Assuming the spammers make comments by just submitting HTTP requests from a perl script or something, 
we thought of a relatively easy fix.  Add some new hidden fields, and have the server read from those hidden fields, 
and then have some javascript to copy content from the existing text fields to the hidden fields onsumbit.  The only 
hassle there is is the spammers learn what the hidden field names are, and adjust their perl scripts.  To combat
that we'd have to dynamically generate hidden field names, which could be tossed in viewstate without too much fuss.
Then the spammers would have to do web crawling, instantiating and controlling a browser so they could get the names
right.
<br /><br />
One bad thought we had was to integrate <a href="http://spambayes.sourceforge.net/">SpamBayes</a>, the excellent, 
excellent spam filter that you should really be running if you use Outlook.  Seed SpamBayes with good comments, then have 
it show/hide comments according to its statistics.  Then there would need to be a section in the admin for you to 
train the thing, but its certainly doable.<img src ="http://blogs.acceleration.net/ryan/aggbug/490.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>My kingdom for a spec! Arrgh!</title><link>http://blogs.acceleration.net/ryan/archive/2004/12/28/428.aspx</link><pubDate>Tue, 28 Dec 2004 19:05:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2004/12/28/428.aspx</guid><description>Bitching about a lack of specification isn't really anything new, but I find myself with little else to do at the moment.
To tease the requirements from the client, I've really outdone myself this time.  I'm working with a contract management system, and 
depending on different input, it should do various things automatically.  So, I've enumerated the input factors, and have for loops
nested 4 deep to hit all the possibilites, printing them to the screen with handy links.  My hope is that the client can then 
click through and say "that one is behaving badly, it should do X".  The problem arises when the loops generate 36 test cases, 
running 216 queries involving nasty things like triggers and nested cursors, and the whole process takes 10 minutes to complete.  
Hence, the blog entry.&lt;br /&gt;
&lt;br /&gt;
The really depressing part is I'm pretty sure the client isn't going to go through these cases "OK"ing them or rejecting them, and its
just another in a long line of tools I've made to get around the lack of a proper spec.  Luckily, they're paying by the hour, so the
only price being paid is in my patience and sanity.  Oh, and this is another impossible deadline project, so while I'm trying to 
figure out if its what they want, they're shitting bricks because its not done.&lt;br /&gt;
&lt;br /&gt;
Ok, end rant.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/428.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">Bitching about a lack of specification isn't really anything new, but I find myself with little else to do at the moment.
To tease the requirements from the client, I've really outdone myself this time.  I'm working with a contract management system, and 
depending on different input, it should do various things automatically.  So, I've enumerated the input factors, and have for loops
nested 4 deep to hit all the possibilites, printing them to the screen with handy links.  My hope is that the client can then 
click through and say "that one is behaving badly, it should do X".  The problem arises when the loops generate 36 test cases, 
running 216 queries involving nasty things like triggers and nested cursors, and the whole process takes 10 minutes to complete.  
Hence, the blog entry.<br />
<br />
The really depressing part is I'm pretty sure the client isn't going to go through these cases "OK"ing them or rejecting them, and its
just another in a long line of tools I've made to get around the lack of a proper spec.  Luckily, they're paying by the hour, so the
only price being paid is in my patience and sanity.  Oh, and this is another impossible deadline project, so while I'm trying to 
figure out if its what they want, they're shitting bricks because its not done.<br />
<br />
Ok, end rant.<img src ="http://blogs.acceleration.net/ryan/aggbug/428.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>Sheesh</title><link>http://blogs.acceleration.net/ryan/archive/2004/10/25/339.aspx</link><pubDate>Mon, 25 Oct 2004 18:58:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2004/10/25/339.aspx</guid><description>I've noticed with the recent cold weather, people are fucking up their power clock more:
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;10/25- 1 fix&lt;/li&gt;
&lt;li&gt;10/22- 2 fixes&lt;/li&gt;
&lt;li&gt;10/20- 1 fix&lt;/li&gt;
&lt;li&gt;10/18- 1 fix&lt;/li&gt;
&lt;li&gt;10/15- 1 fix&lt;/li&gt;
&lt;/ul&gt;

Pull it together, folks, at some point I should do actual work!&lt;br /&gt;
&amp;lt;/rant&amp;gt;&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/339.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml">I've noticed with the recent cold weather, people are fucking up their power clock more:
<br />
<ul>
<li>10/25- 1 fix</li>
<li>10/22- 2 fixes</li>
<li>10/20- 1 fix</li>
<li>10/18- 1 fix</li>
<li>10/15- 1 fix</li>
</ul>

Pull it together, folks, at some point I should do actual work!<br />
&lt;/rant&gt;<img src ="http://blogs.acceleration.net/ryan/aggbug/339.aspx" width = "1" height = "1" /></body></item><item><dc:creator>Ryan</dc:creator><title>Seven Simple Rules for Dealing with your Software Developer Friend</title><link>http://blogs.acceleration.net/ryan/archive/2004/10/21/336.aspx</link><pubDate>Thu, 21 Oct 2004 14:12:00 GMT</pubDate><guid>http://blogs.acceleration.net/ryan/archive/2004/10/21/336.aspx</guid><description>&lt;a href="http://mohammad.abdulfatah.net/mohammad/archives/2004/10/seven_simple_ru.php#more"&gt;Seven Simple Rules for Dealing with your Software Developer Friend&lt;/a&gt;.  Nice, short read.&lt;img src ="http://blogs.acceleration.net/ryan/aggbug/336.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><a href="http://mohammad.abdulfatah.net/mohammad/archives/2004/10/seven_simple_ru.php#more">Seven Simple Rules for Dealing with your Software Developer Friend</a>.  Nice, short read.<img src ="http://blogs.acceleration.net/ryan/aggbug/336.aspx" width = "1" height = "1" /></body></item></channel></rss>