<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-38916088</id><updated>2011-11-27T19:31:44.316-05:00</updated><category term='daytabase'/><category term='xml'/><category term='cool tools'/><category term='concurrent threading series'/><category term='coldfusion'/><category term='j#'/><category term='java'/><category term='sql'/><category term='blog'/><category term='security'/><category term='vb.net'/><category term='user defined functions'/><title type='text'>Crossed Logic</title><subtitle type='html'>A technology blog, focusing on programming in languages like Java, Visual Basic .NET, Coldfusion, and transact SQL (T-SQL).</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-38916088.post-3556225799496438101</id><published>2011-09-17T13:01:00.003-04:00</published><updated>2011-09-17T13:04:57.030-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='daytabase'/><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><title type='text'>DaytaBase.org</title><content type='html'>I will be blogging SQL syntax at &lt;a href="http://daytabase.org"&gt;http://DaytaBase.org&lt;/a&gt; from now on, but may make plans for Crossed Logic in the future. For now, this will be an archive to maintain any links from Articles. For new content, please go to &lt;a href="http://daytabase.org"&gt;http://DaytaBase.org&lt;/a&gt;. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thanks!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-3556225799496438101?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/3556225799496438101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=3556225799496438101' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3556225799496438101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3556225799496438101'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2011/09/daytabaseorg.html' title='DaytaBase.org'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-6504255108418286066</id><published>2010-09-11T08:57:00.004-04:00</published><updated>2010-09-11T09:05:46.424-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>A MySQL Tidbit: Dynamic Export To_XML Stored Procedure</title><content type='html'>&lt;b style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;All XML, All the Time; More Fun MySQL Tidbits – Dynamically Generate XML via Stored Procedure in MySQL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Extensible Markup Language (XML) and database systems, a marriage we are seeing more and more of.  So the topics of parsing and manipulating XML, importing and exporting XML files, etcetera using SQL are pretty commonplace here at Experts Exchange.&lt;br /&gt;&lt;br /&gt;Consequently, in two of my previous &lt;i style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;MySQL tidbits&lt;/i&gt;, I covered some real questions from &lt;a href="http://www.experts-exchange.com/Database/MySQL/"&gt;EE's Q&amp;amp;A forum&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="indent" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 5px; margin-right: 0px; margin-bottom: 0px; margin-left: 20px; "&gt;&lt;a target="_blank" href="http://www.experts-exchange.com/Database/MySQL/A_3574.html" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(119, 119, 119); cursor: pointer; "&gt;A MySQL Tidbit: In-line XML Parsing&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.experts-exchange.com/Database/MySQL/A_3622.html" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(119, 119, 119); cursor: pointer; "&gt;A MySQL Tidbit: In-line CSV Parsing (Using XML)&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;While writing those articles and participating in the mentioned questions, I was urged by a fellow database expert to write some tips on the importing and exporting of XML, specifically in SQL using MySQL database server.  As a result, this particular installment of my SQL tidbits will cover: (1) dynamically constructing XML elements from a given table structure; and (2) exporting a result set to XML file.&lt;br /&gt;&lt;br /&gt;The end product will be a technique you can customize and test for your own XML needs.  This technique will be shown in a stored procedure.  For beginning MySQL readers, I will be providing some background tips -- explanations on some of the inner workings of the SQL code in the procedure...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://goo.gl/RLWY"&gt;Read more of "A MySQL Tidbit: Dynamic Export To_XML Stored Procedure" on Experts-Exchange.com/articles...&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-6504255108418286066?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/6504255108418286066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=6504255108418286066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/6504255108418286066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/6504255108418286066'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2010/09/mysql-tidbit-dynamic-export-toxml.html' title='A MySQL Tidbit: Dynamic Export To_XML Stored Procedure'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-7787257435615805429</id><published>2010-08-07T12:38:00.002-04:00</published><updated>2010-09-11T09:13:48.252-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>A SQL Tidbit: Conditional Aggregates</title><content type='html'>&lt;blockquote&gt;As they say in love and is true in SQL: you can sum some Data some of the time, but you can't always aggregate all Data all the time!&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;By the end of my Experts-Exchange Article, &lt;a href="http://www.experts-exchange.com/A_3527.html"&gt;A SQL Tidbit: Conditional Aggregates&lt;/a&gt;, it is my intention to bring the meaning and value of the above quote to those who chose to read this whether as a beginning SQL programmer or an intermediate one inexperienced with this little tidbit of SQL syntax: conditional aggregation.&lt;br /&gt;&lt;br /&gt;Conditional aggregation is simply the use of aggregates under one or more conditions, thus, potentially altering your results of functions like &lt;span style="font-style:italic;"&gt;SUM()&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;COUNT()&lt;/span&gt;, etcetera in a particular column while allowing you to analyze your record set as a whole...&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.experts-exchange.com/Programming/Languages/SQL_Syntax/A_3527-A-SQL-Tidbit-Conditional-Aggregates.html"&gt;Read more about my SQL tidbit on Conditional Aggregates at Experts-Exchange.com/articles...&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-7787257435615805429?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/7787257435615805429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=7787257435615805429' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7787257435615805429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7787257435615805429'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2010/08/sql-tidbit-conditional-aggregates.html' title='A SQL Tidbit: Conditional Aggregates'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-2644553982856570597</id><published>2009-07-27T16:11:00.003-04:00</published><updated>2009-07-27T17:03:00.452-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Expiration Date Validation Example</title><content type='html'>Here is a simple example of a utility that can validate expirations dates like '0609' or '0710' as being valid expiration dates (i.e., is the date before the current month or not).&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Utility function to determine if a four character expiration date is valid OR not!&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt; * &lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param s&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt; * &amp;lt;p&amp;gt;Date string in format MMyy.  e.g., '0609' as date 'June 2009'.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @return &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; flag indicating if expiration date is valid or not.&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; boolean isValidExpiration(String s) {&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// use SimpleDateFormat to parse values like '0609' as date 'June 2009'&lt;/span&gt;&lt;br /&gt;    java.text.DateFormat sdf = &lt;span class="kwrd"&gt;new&lt;/span&gt; java.text.SimpleDateFormat(&lt;span class="str"&gt;"MMyy"&lt;/span&gt;);&lt;br /&gt;    &lt;br /&gt;    &lt;span class="rem"&gt;// establish current date as last day of previous month at 23:59:59&lt;/span&gt;&lt;br /&gt;    java.util.Calendar now = java.util.Calendar.getInstance(); &lt;br /&gt;    now.set(now.get(java.util.Calendar.YEAR), now.get(java.util.Calendar.MONTH), 0, 23, 59, 59);&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;try&lt;/span&gt; {&lt;br /&gt;        &lt;span class="rem"&gt;// actual parsing of the date, wrapped in try/catch &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// parses as 1st day of month at midnight since only providing month and year&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// e.g., '0609' becomes 'June 01, 2009 00:00:00'&lt;/span&gt;&lt;br /&gt;        java.util.Date exp = sdf.parse(s);&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// if parsed date is before current month, then return invalid!&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (exp.before(now.getTime())) &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;    } &lt;span class="kwrd"&gt;catch&lt;/span&gt; (java.text.ParseException e) {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;  &lt;span class="rem"&gt;// if not MMYY then reject&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// valid if made it this far, can do in reverse by using !exp.before and return true above.&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-2644553982856570597?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/2644553982856570597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=2644553982856570597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/2644553982856570597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/2644553982856570597'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2009/07/expiration-date-validation-example.html' title='Expiration Date Validation Example'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-3143064656534285617</id><published>2009-06-04T18:02:00.008-04:00</published><updated>2009-09-06T04:02:30.640-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Other Experts Exchange Articles</title><content type='html'>&lt;div&gt;SQL Syntax:&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.experts-exchange.com/viewArticle.jsp?aid=252"&gt;Mimic IsNumeric Functionality Using RegExp in MySQL&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.experts-exchange.com/viewArticle.jsp?aid=654"&gt;Pivot Reporting Tips for SQL Server: Handling Rolling Periods Without Using Dynamic SQL&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.experts-exchange.com/viewArticle.jsp?aid=811"&gt;Converting Active Directory Timestamps in Microsoft SQL Server&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Java Programming:&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.experts-exchange.com/viewArticle.jsp?aid=351"&gt;Custom File Filtering Using Java File Choosers&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-3143064656534285617?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/3143064656534285617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=3143064656534285617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3143064656534285617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3143064656534285617'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2009/06/other-experts-exchange-articles.html' title='Other Experts Exchange Articles'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-5421770321177799814</id><published>2008-11-11T19:59:00.003-05:00</published><updated>2008-11-11T20:27:16.785-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Java Custom Comparators: Sorting Text and Numbers Independently</title><content type='html'>Comparing strings and sorting lists of strings in Java is normally very simple as the API provides a nice means of comparing two strings as text. However, the need occasionally arises when we have values stored that can be either numeric or text or a combination thereof.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;String[] inputStringArray = { &lt;span class="str"&gt;"1"&lt;/span&gt;, &lt;span class="str"&gt;"19"&lt;/span&gt;, &lt;span class="str"&gt;"2"&lt;/span&gt;, &lt;span class="str"&gt;"3pt1"&lt;/span&gt;, &lt;span class="str"&gt;"3"&lt;/span&gt;, &lt;span class="str"&gt;"5pt1"&lt;/span&gt;, &lt;span class="str"&gt;"6pt2"&lt;/span&gt;, &lt;span class="str"&gt;"7pt3"&lt;/span&gt;, &lt;span class="str"&gt;"7pt3"&lt;/span&gt;, &lt;span class="str"&gt;"10"&lt;/span&gt;, &lt;span class="str"&gt;"10x1"&lt;/span&gt;, &lt;span class="str"&gt;"15"&lt;/span&gt;, &lt;span class="str"&gt;"7"&lt;/span&gt;, &lt;span class="str"&gt;"A7"&lt;/span&gt;, &lt;span class="str"&gt;"B87"&lt;/span&gt;, &lt;span class="str"&gt;"10pt5"&lt;/span&gt; };&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;// The input is a String array. Make that an ArrayList:&lt;/span&gt;&lt;br /&gt;java.util.List&amp;lt;String&amp;gt; inputList = &lt;span class="kwrd"&gt;new&lt;/span&gt; java.util.ArrayList&amp;lt;String&amp;gt;(java.util.Arrays.asList(inputStringArray));&lt;/pre&gt;&lt;br /&gt;Say we have the above input array of string values that we have converted to an ArrayList&lt;t&gt; as shown and now want to sort. In steps custom comparators. The easiest way to implement one is using an anonymous nested class at the point of use which will allow the flexibility of sorting differently each time Collections.sort() is called. If you find you need this more often, then convert this to a standalone class that implements the Comparator interface.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; java.util.List&amp;lt;String&amp;gt; sort(java.util.List&amp;lt;String&amp;gt; list) {&lt;br /&gt;    java.util.Collections.sort(list, &lt;span class="kwrd"&gt;new&lt;/span&gt; java.util.Comparator&amp;lt;String&amp;gt;() {&lt;br /&gt;        &lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         * Custom compare to sort numbers as numbers.&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         * Strings as strings, with numbers ordered before strings.&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         * &lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         * @param o1&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         * @param o2&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         * @return&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;         */&lt;/span&gt;&lt;br /&gt;        @Override&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; compare(String o1, String o2) {&lt;br /&gt;            boolean isFirstNumeric, isSecondNumeric;&lt;br /&gt;        &lt;br /&gt;            isFirstNumeric = o1.matches(&lt;span class="str"&gt;"\\d+"&lt;/span&gt;);&lt;br /&gt;            isSecondNumeric = o2.matches(&lt;span class="str"&gt;"\\d+"&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (isFirstNumeric) {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (isSecondNumeric) {&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; Integer.valueOf(o1).compareTo(Integer.valueOf(o2));&lt;br /&gt;                } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; -1; &lt;span class="rem"&gt;// numbers always smaller than letters&lt;/span&gt;&lt;br /&gt;                }&lt;br /&gt;            } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (isSecondNumeric) {&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; 1; &lt;span class="rem"&gt;// numbers always smaller than letters&lt;/span&gt;&lt;br /&gt;                } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;                    isFirstNumeric = o1.split(&lt;span class="str"&gt;"[^0-9]"&lt;/span&gt;)[0].matches(&lt;span class="str"&gt;"\\d+"&lt;/span&gt;);&lt;br /&gt;                    isSecondNumeric = o2.split(&lt;span class="str"&gt;"[^0-9]"&lt;/span&gt;)[0].matches(&lt;span class="str"&gt;"\\d+"&lt;/span&gt;);&lt;br /&gt;                &lt;br /&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (isFirstNumeric) {&lt;br /&gt;                        &lt;span class="kwrd"&gt;if&lt;/span&gt; (isSecondNumeric) {&lt;br /&gt;                            &lt;span class="kwrd"&gt;int&lt;/span&gt; intCompare = Integer.valueOf(o1.split(&lt;span class="str"&gt;"[^0-9]"&lt;/span&gt;)[0]).compareTo(Integer.valueOf(o2.split(&lt;span class="str"&gt;"[^0-9]"&lt;/span&gt;)[0]));&lt;br /&gt;                            &lt;span class="kwrd"&gt;if&lt;/span&gt; (intCompare == 0) {&lt;br /&gt;                                &lt;span class="kwrd"&gt;return&lt;/span&gt; o1.compareToIgnoreCase(o2);&lt;br /&gt;                            }&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; intCompare;&lt;br /&gt;                        } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; -1; &lt;span class="rem"&gt;// numbers always smaller than letters&lt;/span&gt;&lt;br /&gt;                        }&lt;br /&gt;                    } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;                        &lt;span class="kwrd"&gt;if&lt;/span&gt; (isSecondNumeric) {&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; 1; &lt;span class="rem"&gt;// numbers always smaller than letters&lt;/span&gt;&lt;br /&gt;                        } &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; o1.compareToIgnoreCase(o2);&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; list;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The above does the following:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Determines if the strings being compared are numeric values or not, using regular expression to match on \d which signifies a numeric digit.&lt;/li&gt;&lt;li&gt;If both values are numeric, then we compare as integers using its already implemented compareTo function.&lt;/li&gt;&lt;li&gt;If only one of the values is numeric, then it is the smallest as we want the numbers to sort first.&lt;/li&gt;&lt;li&gt;If both are non-numeric, then we simply compare as strings. However, to show extended support for our third case of blended numbers and text, we go through same logic as above on the two string values: if both begin with numbers, then compare as integers with difference that equal numbers then need to sort by text; if one begins with a number, then it is smaller; if both are text, then just compare as strings.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Hopefully that is clear, but to test the results, you can use the following code:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;java.util.List&amp;lt;String&amp;gt; sortedList = sort(inputList);&lt;br /&gt;&lt;br /&gt;System.&lt;span class="kwrd"&gt;out&lt;/span&gt;.println(&lt;span class="str"&gt;"Numbers and text sorted!"&lt;/span&gt;);&lt;br /&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (String s : sortedList) {&lt;br /&gt;    System.&lt;span class="kwrd"&gt;out&lt;/span&gt;.println(s);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Hope that helps.&lt;br /&gt;&lt;br /&gt;Happy coding!&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html#sum"&gt;Java Regular Expression Syntax&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Comparator.html"&gt;Comparator Interface&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-5421770321177799814?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/5421770321177799814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=5421770321177799814' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/5421770321177799814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/5421770321177799814'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/11/java-custom-comparators-sorting-text.html' title='Java Custom Comparators: Sorting Text and Numbers Independently'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-8774492202174823282</id><published>2008-10-12T21:15:00.001-04:00</published><updated>2008-10-12T21:26:17.955-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>String to Value Algorithm</title><content type='html'>Well continuing on the thought of conversion routines, here is an example of taking a string value in Transact-SQL on Microsoft SQL Server (may work on other platforms that support same functions) and creating a unique integer value.&lt;br /&gt;&lt;br /&gt;Code listing:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @text nvarchar(100), @&lt;span class="kwrd"&gt;value&lt;/span&gt; bigint&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @text = &lt;span class="str"&gt;'Smith'&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;value&lt;/span&gt; = 0&lt;br /&gt;&lt;span class="kwrd"&gt;WHILE&lt;/span&gt; LEN(@text) &amp;gt; 0&lt;br /&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;value&lt;/span&gt; = @&lt;span class="kwrd"&gt;value&lt;/span&gt; + ASCII(&lt;span class="kwrd"&gt;LEFT&lt;/span&gt;(@text, 1)) * square(LEN(@text))&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @text = &lt;span class="kwrd"&gt;RIGHT&lt;/span&gt;(@text, LEN(@text) - 1)&lt;br /&gt;&lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @value&lt;/pre&gt;&lt;p&gt;Very simple hopefully. The basis is using the length of the string, create a large integer value that is multiplied against the ascii value of each letter in the string. I was asked this as a question, so I have not explored all of the uses of a function like this; however, as a quick hash it seems to work fine.&lt;br /&gt;&lt;br /&gt;Again, just posting for the learning of some of the tools available in SQL like the ASCII and SQUARE functions. Hopefully making the life of some other DBA or programmer a little easier.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;BigInt: &lt;a href="http://msdn.microsoft.com/en-us/library/ms187745(SQL.90).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms187745(SQL.90).aspx&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Numeric: &lt;a href="http://msdn.microsoft.com/en-us/library/ms187746(SQL.90).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms187746(SQL.90).aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;ASCII: &lt;a href="http://msdn.microsoft.com/en-us/library/ms177545.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms177545.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Square: &lt;a href="http://msdn.microsoft.com/en-us/library/ms173569.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms173569.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-8774492202174823282?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/8774492202174823282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=8774492202174823282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8774492202174823282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8774492202174823282'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/10/string-to-value-algorithm.html' title='String to Value Algorithm'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-8011476595160685758</id><published>2008-09-21T01:43:00.006-04:00</published><updated>2008-10-12T21:27:45.325-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Converting Between String, ASCII, And Hex In .NET</title><content type='html'>Welcome again to my twisted mind.  This post is just a quick example on converting between string, ascii and hexadecimal values using the .NET, specifically visual basic .NET programming.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; strOrig &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = &lt;span class="str"&gt;"Hello"&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; decimals &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of &lt;span class="kwrd"&gt;Decimal&lt;/span&gt;)()&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; hexStrs &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)()&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; intCurrent &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Double&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; c &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Char&lt;/span&gt; &lt;span class="kwrd"&gt;In&lt;/span&gt; strOrig.ToCharArray()&lt;br /&gt;    intCurrent = Strings.Asc(c)&lt;br /&gt;    decimals.Add(intCurrent)&lt;br /&gt;    hexStrs.Add(Conversion.Hex(intCurrent))&lt;br /&gt;&lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;If&lt;/span&gt; hexStrs.Count &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;    Console.Write(&lt;span class="str"&gt;"Hex: "&lt;/span&gt; &amp;amp; hexStrs(0))&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; (hexStrs.Count - 1)&lt;br /&gt;        Console.Write(&lt;span class="str"&gt;" "&lt;/span&gt; &amp;amp; hexStrs(i))&lt;br /&gt;    &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    Console.WriteLine(&lt;span class="str"&gt;""&lt;/span&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;If&lt;/span&gt; decimals.Count &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;    Console.Write(&lt;span class="str"&gt;"Decimals: "&lt;/span&gt; &amp;amp; decimals(0))&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; (decimals.Count - 1)&lt;br /&gt;        Console.Write(&lt;span class="str"&gt;" "&lt;/span&gt; &amp;amp; decimals(i))&lt;br /&gt;    &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    Console.WriteLine(&lt;span class="str"&gt;""&lt;/span&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Console.ReadLine()&lt;/pre&gt;As you can see above, .NET provides some nice conversion utilities for ascii value of a character and converting a decimal value to hexidecimal making the solution very straightforward as we just need to create a character array from string value and then convert each character to its ascii equivalent. Furthermore, we can quickly get the hexidecimal value for the character.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This is not rocket science by any stretch, but like posting things like this even as simple as it is so I for one don't forget it and to help another programmer get started on something more complex.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Anyway, for now that is it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Happy programming. &lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.c-sharpcorner.com/UploadFile/Joshy_geo/HexConverter10282006021521AM/HexConverter.aspx?ArticleID=fe25819d-12f1-4a06-9d3f-422b6c46a1f9"&gt;How to convert string to hexadecimal and vice versa (C#)&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Conversion.Hex: &lt;a href="http://msdn.microsoft.com/en-us/library/f480a85s.aspx"&gt;http://msdn.microsoft.com/en-us/library/f480a85s.aspx&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Strings.Asc: &lt;a href="http://msdn.microsoft.com/en-us/library/78sb8546.aspx"&gt;http://msdn.microsoft.com/en-us/library/78sb8546.aspx&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-8011476595160685758?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/8011476595160685758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=8011476595160685758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8011476595160685758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8011476595160685758'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/converting-between-string-ascii-and-hex.html' title='Converting Between String, ASCII, And Hex In .NET'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-8463834237132911474</id><published>2008-09-19T15:58:00.002-04:00</published><updated>2008-09-19T16:35:14.264-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>Using SQL To Find Work Days In Date Range II</title><content type='html'>In &lt;a href="http://crossedlogic.blogspot.com/2008/09/using-sql-to-find-work-days-in-date.html"&gt;Using SQL To Find Work Days In Date Range&lt;/a&gt;, we created our fn_GetWorkDaysInRange user defined function in Microsoft SQL Server 2005. However, through our research into VB.NET and other simpler algorithms if you have been reading along, if we can do it better why not learn how.&lt;br /&gt;&lt;br /&gt;So not to leave well enough alone, here is the code listing our fn_GetWorkDaysInRange revisited:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; [dbo].[fn_GetWorkDaysInRange]&lt;br /&gt;(&lt;br /&gt;    @startDate datetime    &lt;span class="rem"&gt;-- first datetime in range&lt;/span&gt;&lt;br /&gt;    , @endDate datetime &lt;span class="rem"&gt;-- last datetime in range (can be in past)&lt;/span&gt;&lt;br /&gt;    , @includeStartDate &lt;span class="kwrd"&gt;bit&lt;/span&gt; &lt;span class="rem"&gt;-- flag to include start date as a work day&lt;/span&gt;&lt;br /&gt;    , @firstWkndDay &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="rem"&gt;-- first day of weekend (e.g. Day(datetime))&lt;/span&gt;&lt;br /&gt;    , @lastWkndDay &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="rem"&gt;-- last day of weekend (e.g. Day(datetime))&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- variables used in processing&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @workDays &lt;span class="kwrd"&gt;int&lt;/span&gt;, @sign &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- parse input and calculate direction of date range&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @firstWkndDay = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@firstWkndDay, 0)&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @lastWkndDay = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@lastWkndDay, @firstWkndDay)&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @startDate = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@startDate, getdate())&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @endDate = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@endDate, @startDate)&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @sign = Sign(DateDiff(dd, @startdate, @enddate))&lt;br /&gt;   &lt;br /&gt;    &lt;span class="rem"&gt;-- set initial value of work days result based on include start date value&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- we use sign so that end dates older than start return negative work days&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- for work days to come up as positive value no matter what, sign usage can be replace by 1&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @workDays = &lt;span class="kwrd"&gt;CASE&lt;/span&gt; @includeStartDate &lt;span class="kwrd"&gt;WHEN&lt;/span&gt; 0 &lt;span class="kwrd"&gt;THEN&lt;/span&gt; 0 &lt;span class="kwrd"&gt;ELSE&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;CASE&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;WHEN&lt;/span&gt; DatePart(dw, @startDate) &lt;span class="kwrd"&gt;IN&lt;/span&gt; (@firstWkndDay, @lastWkndDay)&lt;br /&gt;            &lt;span class="kwrd"&gt;THEN&lt;/span&gt; 0&lt;br /&gt;            &lt;span class="kwrd"&gt;ELSE&lt;/span&gt; &lt;span class="kwrd"&gt;Case&lt;/span&gt; @sign &lt;span class="kwrd"&gt;When&lt;/span&gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt; 1 &lt;span class="kwrd"&gt;Else&lt;/span&gt; @sign &lt;span class="kwrd"&gt;End&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;   &lt;br /&gt;    &lt;span class="rem"&gt;-- while end date is not equal to start date add sign (-1/1) number of days&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- and add to work days total if not a weekend&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;WHILE&lt;/span&gt; DateDiff(dd, @startDate, @endDate) &amp;lt;&amp;gt; 0&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @startDate = DateAdd(dd, @sign, @startDate)&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @workDays = @workDays +&lt;br /&gt;            &lt;span class="kwrd"&gt;CASE&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;WHEN&lt;/span&gt; DatePart(dw, @startDate) &lt;span class="kwrd"&gt;IN&lt;/span&gt; (@firstWkndDay, @lastWkndDay)&lt;br /&gt;                &lt;span class="kwrd"&gt;THEN&lt;/span&gt; 0&lt;br /&gt;                &lt;span class="kwrd"&gt;ELSE&lt;/span&gt; @sign&lt;br /&gt;            &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- return working days result to caller&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; @workDays&lt;br /&gt;END&lt;/pre&gt;The number of lines look very similar, but if you closely inspect this new version there are many changes/simplifications. The table variable is no longer needed, removing further dependence on new version(s) of SQL. The logic is reduced to while loop with two execution lines: increment/decrement date value; add to work days total if the new date value is a working day. The extra code is for readability of case logic.&lt;br /&gt;&lt;br /&gt;To have this reflect how clean it really is, we can abstract out the logic for weekend which gets rid of the parameters and set statements for weekend day along with extensive case logic.  We could then extend that separate function named something like fn_IsNotWeekDay to include logic to check date against our holiday table returning a bit flagging weekend/holiday.  With CLR based user defined functions like we explored using VB.NET, this logic can be as complex as we are capable of coding in either SQL or .NET.&lt;br /&gt;&lt;br /&gt;Until the next learning adventure.&lt;br /&gt;&lt;br /&gt;Keep the code alive!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Related Articles/References:&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/using-sql-to-find-work-days-in-date.html"&gt;Using SQL To Find Work Days In Date Range&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/converting-working-days-to-calendar.html"&gt;Converting Working Days To Calendar Days Using SQL&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/converting-between-calendar-and-working.html"&gt;Converting Between Calendar And Working Days In VB.NET&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-8463834237132911474?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/8463834237132911474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=8463834237132911474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8463834237132911474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8463834237132911474'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/using-sql-to-find-work-days-in-date_19.html' title='Using SQL To Find Work Days In Date Range II'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-4491129122573217060</id><published>2008-09-17T21:12:00.008-04:00</published><updated>2008-09-19T10:27:17.409-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Converting Between Calendar And Working Days In VB.NET</title><content type='html'>With all the fun of creating functionality similar to this in SQL, made some optimizations within original VB.NET functions for converting between calendar and working/business days and got to thinking it would be good to start taking advantage of the fact that SQL 2005 supports CLR assemblies. Instead of having to do overly complex SQL functions/queries/procedures, use SQL CLR as it will make your life much easier and you will look cool doing it.&lt;br /&gt;&lt;br /&gt;Furthermore, is too easy not to. To convert my utility class already containing public shared functions for dealing with going back and forth between working and calendar days, I simply added the two imports shown in the code listing below; Partial identifier to my class; &amp;lt;SqlFunction()&amp;gt; to each method I want exposed to CLR. Even if I went the next step to convet to SqlTypes defined in the first import, that is not too difficult.&lt;br /&gt;&lt;br /&gt;Well let's dive into the code listing:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System.Data.SqlTypes&lt;br /&gt;&lt;span class="kwrd"&gt;Imports&lt;/span&gt; Microsoft.SqlServer.Server&lt;br /&gt;&lt;br /&gt;Partial &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; MyFirstUDFn&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' Get calendar days from today equivalent to working days specified.&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;param name="wrkDays"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;SqlFunction()&amp;gt; _&lt;br /&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; CalendarDaysFromWorkDays(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; wrkDays &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;'Using integer division, get the whole number of work weeks &lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; calDays &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = (wrkDays \ 5) * 7&lt;br /&gt;        calDays += (wrkDays &lt;span class="kwrd"&gt;Mod&lt;/span&gt; 5) &lt;span class="rem"&gt;'Add back the remaining work days&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;'Adjust result to fall on working day as originally intended&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;While&lt;/span&gt; IsWeekend(DateAdd(DateInterval.Day, calDays, &lt;span class="kwrd"&gt;Date&lt;/span&gt;.Now()))&lt;br /&gt;            calDays += Math.Sign(wrkDays)&lt;br /&gt;        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;While&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Return&lt;/span&gt; calDays&lt;br /&gt;    &lt;span class="kwrd"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;'Create list of weekend days - for US this is Saturday (7) and Sunday (1)&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; WEEKEND_DAYS &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of &lt;span class="kwrd"&gt;Integer&lt;/span&gt;)(&lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;() {7, 1})&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' Returns flag indicating if date is a weekend day or not.&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;param name="calDate"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;SqlFunction()&amp;gt; _&lt;br /&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; IsWeekend(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; calDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Return&lt;/span&gt; WEEKEND_DAYS.Contains(Weekday(calDate))&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' Get working days from today equivalent to calendar days specified.&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;param name="calDays"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;SqlFunction()&amp;gt; _&lt;br /&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; WorkDaysFromCalendarDays(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; calDays &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; wrkDays &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;If&lt;/span&gt; calDays &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; calDays&lt;br /&gt;                &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; IsWeekend(DateAdd(DateInterval.Day, i, &lt;span class="kwrd"&gt;Date&lt;/span&gt;.Now())) &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                    wrkDays += 1&lt;br /&gt;                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;ElseIf&lt;/span&gt; calDays &amp;lt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = calDays &lt;span class="kwrd"&gt;To&lt;/span&gt; (-1)&lt;br /&gt;                &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; IsWeekend(DateAdd(DateInterval.Day, i, &lt;span class="kwrd"&gt;Date&lt;/span&gt;.Now())) &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                    wrkDays -= 1&lt;br /&gt;                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Return&lt;/span&gt; wrkDays&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; Class&lt;/pre&gt;As you have noticed by now, the function logic look incredibly similar to the code we explored in our SQL adventure. As stated, the SQL code originated from the CalendarDaysFromWorkDays function and its counterpart; however, the code for WorkDaysFromCalendarDays is more like our SQL solution that its original just simplier form since these functions are used for a set number of days from current date versus a date range; however, the principles are the same.&lt;br /&gt;&lt;br /&gt;One of the additions, is extending this to work with different weekend days and the bonus IsWeekend function that came as a result of implementing that. We could easily extend this to query for holidays and have a function for IsHoliday as well. See the reference to Using conn As New SqlConnection("context connection=true") within the Microsoft Solutions Developer Network (MSDN) link below.&lt;br /&gt;&lt;br /&gt;Anyway, where do we go from here. Well the simple step is to create a SQL Server Project! For those of you using Visual Studio 2005/2008 Express as I am on one machine, you are probably asking yourself "What SQL Server Project?". Exactly. This is available in the full version of Visual Studio, so here is what I did to develop this in VS Express.&lt;br /&gt;&lt;br /&gt;Create a new Class Library project in VS and ensure that you go into the properties of the project and remove the root namespace (you can leave this as-is or change to another namespace to have structured classes, but just take note of that for later as using methods within assemblies are of the format AssemblyName.ClassName.MethodName so if you have a class in a long namespace it must be declared like AssemblyName.[NamespaceName.ClassName].MethodName). Add a class item to your project and code away. Above code functions as-is and is a good example of all that is needed to make a normal VB function to SqlFunction or sub to SqlStoredProcedure.&lt;br /&gt;&lt;br /&gt;Once compiled to a DLL, the do the following on the SQL Server:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;sp_configure N&lt;span class="str"&gt;'clr enabled'&lt;/span&gt;, 1&lt;br /&gt;&lt;span class="kwrd"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;reconfigure&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;go&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; ASSEMBLY MyAssembly &lt;span class="kwrd"&gt;FROM&lt;/span&gt; &lt;span class="str"&gt;'C:\SQLCLRProject.dll'&lt;/span&gt; &lt;span class="kwrd"&gt;WITH&lt;/span&gt; PERMISSION_SET = SAFE&lt;/pre&gt;Once you have the assembly created and CLR enabled, you can issue this SQL to test:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- creates the function&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; udf_IsWeekend(@calDate datetime) &lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; &lt;span class="kwrd"&gt;bit&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;EXTERNAL&lt;/span&gt; NAME SQLUserDefinedFunctions.MyFirstUDFn.IsWeekend&lt;br /&gt;&lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- example usage&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; dbo.udf_IsWeekend(DateAdd(dd, 2, getdate()))&lt;/pre&gt;Now you are using your original .NET code in SQL server and no need to pull your here out finding SQL equivalents to pre-existing .NET functions. Although, that is fun in and of itself, sometimes you just need to save time and practicing code resuse is always a good thing.&lt;br /&gt;&lt;br /&gt;Hope that helps!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Related Articles/References:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/using-sql-to-find-work-days-in-date.html"&gt;Using SQL To Find Work Days In Date Range&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/converting-working-days-to-calendar.html"&gt;Converting Working Days To Calendar Days Using SQL&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Using CLR Integration in SQL Server 2005: &lt;a href="http://msdn.microsoft.com/en-us/library/ms345136.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms345136.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;SQL Server DBA Guide to SQLCLR: &lt;a href="http://www.sqlskills.com/resources/Whitepapers/SQL%20Server%20DBA%20Guide%20to%20SQLCLR.htm"&gt;http://www.sqlskills.com/resources/Whitepapers/SQL%20Server%20DBA%20Guide%20to%20SQLCLR.htm&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-4491129122573217060?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/4491129122573217060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=4491129122573217060' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/4491129122573217060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/4491129122573217060'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/converting-between-calendar-and-working.html' title='Converting Between Calendar And Working Days In VB.NET'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-7496107630435521897</id><published>2008-09-17T20:26:00.004-04:00</published><updated>2008-09-17T20:45:17.459-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>Converting Working Days To Calendar Days Using SQL</title><content type='html'>In the &lt;a href="http://crossedlogic.blogspot.com/2008/09/using-sql-to-find-work-days-in-date.html"&gt;Using SQL To Find Work Days In Date Range&lt;/a&gt; post I mentioned that I original thought it would be an easy conversion from calendar days to work days as using simple mathematical formula in SQL, you can get calendar days or a calendar date from working days. It was my thought that the opposite of this formula would work; however, that is another post you can read at your leisure. In this post, I figured I would share my simply formula. It is so straight forward that hopefully it will save you from wasting time going for a more complex approach.&lt;br /&gt;&lt;br /&gt;Here is the code listing:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @workDays &lt;span class="kwrd"&gt;int&lt;/span&gt;, @calDays &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @workDays = 3&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- using integer division to convert work weeks to calendar weeks&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- AND modulus division to get partial week's days&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @calDays = @workDays / 5 * 7 + @workDays % 5&lt;br /&gt;&lt;span class="rem"&gt;-- just double check that end result is not on a weekend&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;WHILE&lt;/span&gt; DatePart(dw, DateAdd(dd, @calDays, getdate())) &lt;span class="kwrd"&gt;IN&lt;/span&gt; (7, 1)&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @calDays = @calDays + 1&lt;br /&gt;&lt;span class="rem"&gt;-- select away you have your calendar days and date if you would like&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; DateAdd(dd, @calDays, getdate())&lt;/pre&gt;As I said, pretty straight forward.  Since SQL, at least in Microsoft SQL Server, will treat division of int datatypes as integer division, you will get the whole number amount of weeks represented by work days (i.e. 8/5 = 1).  For other platforms, just use FLOOR function or its equivalent in your code (e.g. Floor(@workDays / 5) or the integer division operator to achieve the same results.  Subsequently, modulus is taken of working days to get the partial week days involved which should be 0 - 4 that we can add to calendar days we calculated from multiplying the number of weeks by 7.&lt;br /&gt;&lt;br /&gt;You can just run in query window as above, but to complement our function/procedure to get working days from a set of calendar dates you can put this in a stored procedure or user defined function the returns the calendar days themselves or the resulting date.&lt;br /&gt;&lt;br /&gt;Keep evolving development!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-7496107630435521897?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/7496107630435521897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=7496107630435521897' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7496107630435521897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7496107630435521897'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/converting-working-days-to-calendar.html' title='Converting Working Days To Calendar Days Using SQL'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-691699663671309169</id><published>2008-09-17T17:15:00.006-04:00</published><updated>2008-09-17T20:13:21.388-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>Using SQL To Find Work Days In Date Range</title><content type='html'>I had a question come up today for Microsoft SQL Server 2005 on how to calculate the number of working/business days between two dates with a requirement that the answer must function in countries where weekend can be variable two days or even one. My first thought was that is simple. Famous last words!&lt;br /&gt;&lt;br /&gt;Eight hours of research later, this article covers the calculation of working days in the date range which appears to work quite nicely. Here is a code listing:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; [dbo].[fn_GetWorkDaysInRange]&lt;br /&gt;(&lt;br /&gt;    @startDate datetime    &lt;span class="rem"&gt;-- first datetime in range&lt;/span&gt;&lt;br /&gt;    , @endDate datetime &lt;span class="rem"&gt;-- last datetime in range (can be in past)&lt;/span&gt;&lt;br /&gt;    , @includeStartDate &lt;span class="kwrd"&gt;bit&lt;/span&gt; &lt;span class="rem"&gt;-- flag to include start date as a work day&lt;/span&gt;&lt;br /&gt;    , @firstWkndDay &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="rem"&gt;-- first day of weekend (e.g. Day(datetime))&lt;/span&gt;&lt;br /&gt;    , @lastWkndDay &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="rem"&gt;-- last day of weekend (e.g. Day(datetime))&lt;/span&gt;&lt;br /&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- variables used in processing&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @workDays &lt;span class="kwrd"&gt;int&lt;/span&gt;, @sign &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; (calendarDate datetime, isWorkDay &lt;span class="kwrd"&gt;bit&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- parse input and calculate direction of date range&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @firstWkndDay = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@firstWkndDay, 0)&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @lastWkndDay = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@lastWkndDay, @firstWkndDay)&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @startDate = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@startDate, getdate())&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @endDate = &lt;span class="kwrd"&gt;Coalesce&lt;/span&gt;(@endDate, @startDate)&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @sign = Sign(DateDiff(dd, @startdate, @enddate))&lt;br /&gt; &lt;br /&gt;    &lt;span class="rem"&gt;-- insert our starting date&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;VALUES&lt;/span&gt; (@startDate, &lt;span class="kwrd"&gt;Case&lt;/span&gt; @includeStartDate &lt;span class="kwrd"&gt;When&lt;/span&gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt; 0 &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- add dates into table from start to end date&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;IF&lt;/span&gt; @sign &amp;gt; 0 &lt;span class="rem"&gt;-- use sign of date difference to determine direction&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt; &lt;br /&gt;        &lt;span class="kwrd"&gt;WHILE&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;MAX&lt;/span&gt;(calendarDate) &lt;span class="kwrd"&gt;FROM&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;) &amp;lt; @enddate&lt;br /&gt;        &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; DateAdd(dd, 1, &lt;span class="kwrd"&gt;MAX&lt;/span&gt;(calendarDate)), &lt;span class="kwrd"&gt;NULL&lt;/span&gt; &lt;span class="kwrd"&gt;FROM&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;ELSE&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;WHILE&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;MIN&lt;/span&gt;(calendarDate) &lt;span class="kwrd"&gt;FROM&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;) &amp;gt; @enddate&lt;br /&gt;        &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt; &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; DateAdd(dd, -1, &lt;span class="kwrd"&gt;MIN&lt;/span&gt;(calendarDate)), &lt;span class="kwrd"&gt;NULL&lt;/span&gt; &lt;span class="kwrd"&gt;FROM&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- update table to tag work days&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;UPDATE&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; isWorkDay = &lt;span class="kwrd"&gt;CASE&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;WHEN&lt;/span&gt; DatePart(dw, calendarDate) &lt;span class="kwrd"&gt;IN&lt;/span&gt; (@firstWkndDay, @lastWkndDay)&lt;br /&gt;            &lt;span class="kwrd"&gt;THEN&lt;/span&gt; 0&lt;br /&gt;            &lt;span class="kwrd"&gt;ELSE&lt;/span&gt; 1&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; isWorkDay &lt;span class="kwrd"&gt;IS&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- select the working days from our table into return variable&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @workDays = &lt;span class="kwrd"&gt;COUNT&lt;/span&gt;(calendarDate) &lt;span class="kwrd"&gt;FROM&lt;/span&gt; @&lt;span class="kwrd"&gt;table&lt;/span&gt; &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; isWorkDay = 1&lt;br /&gt; &lt;br /&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; (@workDays * @sign)&lt;br /&gt;END&lt;/pre&gt;As stated above, this function will remove weekend days between the starting and ending range and thus return number of working days. Once we have that result, we can use a query to retrieve our holidays (or alternatively modify the above to take in a country code and lookup the weekend days and holidays returning the net business days).&lt;br /&gt;&lt;br /&gt;Here is an example of this function's usage&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- create holidays table for testing data&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; [dbo].[Holidays](&lt;br /&gt;    [&lt;span class="kwrd"&gt;day&lt;/span&gt;] [datetime],&lt;br /&gt;    [holiday] [nvarchar](50) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; SQL_Latin1_General_CP1_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br /&gt;    [country] [nvarchar](3) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; SQL_Latin1_General_CP1_CI_AS&lt;br /&gt;) &lt;span class="kwrd"&gt;ON&lt;/span&gt; [&lt;span class="kwrd"&gt;PRIMARY&lt;/span&gt;]&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; Holidays&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="str"&gt;'12/25/2008'&lt;/span&gt;, &lt;span class="str"&gt;'Christmas'&lt;/span&gt;, &lt;span class="str"&gt;'USA'&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;UNION&lt;/span&gt; &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="str"&gt;'12/26/2008'&lt;/span&gt;, &lt;span class="str"&gt;'Day After Christmas'&lt;/span&gt;, &lt;span class="str"&gt;'USA'&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- end creation of table for testing data&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @workDays &lt;span class="kwrd"&gt;int&lt;/span&gt;, @holidays &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @startDate datetime, @endDate datetime&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @startDate = &lt;span class="str"&gt;'12/15/2008'&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SET&lt;/span&gt; @endDate = &lt;span class="str"&gt;'12/29/2008'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @workDays = dbo.fn_GetWorkDaysInRange(@startDate, @endDate, 0, 7, 1)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @holiDays = &lt;span class="kwrd"&gt;COUNT&lt;/span&gt;([&lt;span class="kwrd"&gt;day&lt;/span&gt;])&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Holidays]&lt;br /&gt;&lt;span class="kwrd"&gt;WHERE&lt;/span&gt; [country] = &lt;span class="str"&gt;'USA'&lt;/span&gt; &lt;span class="kwrd"&gt;AND&lt;/span&gt; DatePart(dw, [&lt;span class="kwrd"&gt;day&lt;/span&gt;]) &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;IN&lt;/span&gt; (7, 1)&lt;br /&gt;&lt;span class="kwrd"&gt;AND&lt;/span&gt; [&lt;span class="kwrd"&gt;day&lt;/span&gt;] &lt;span class="kwrd"&gt;BETWEEN&lt;/span&gt; @startDate &lt;span class="kwrd"&gt;AND&lt;/span&gt; @endDate&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;PRINT&lt;/span&gt; (@workDays)&lt;br /&gt;&lt;span class="kwrd"&gt;PRINT&lt;/span&gt; (@holidays)&lt;br /&gt;&lt;span class="kwrd"&gt;PRINT&lt;/span&gt; (@workDays - @holidays)&lt;/pre&gt;&lt;br /&gt;Results come out 10, 2, and 8 for each of the three print statements, respectively.  Exactly what we wanted!  It is a joy when it all works.&lt;br /&gt;&lt;br /&gt;Hopefully this post will save you as long journey, but leave enough uncharted territory to have a little fun with in customizing to your own environment.  I have even played with this myself to replace some logic I was using for determining shop working days, so enjoy.  For those of you not on Microsoft SQL Server 2005, please keep in mind that other versions of Microsoft SQL Server that support user defined functions should work. Consequently, for other platforms or versions, the structure of this code can probably be manipulated to work in a stored procedure and/or using temporary table instead of a table variable and likewise for other features used not present in your system.  The principles should be the same.&lt;br /&gt;&lt;br /&gt;Hope this helps and happy coding!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-691699663671309169?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/691699663671309169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=691699663671309169' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/691699663671309169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/691699663671309169'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/using-sql-to-find-work-days-in-date.html' title='Using SQL To Find Work Days In Date Range'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-139422875324231302</id><published>2008-09-15T23:13:00.005-04:00</published><updated>2008-09-16T01:02:56.087-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>DateSerial In Microsoft SQL Server 2005</title><content type='html'>&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;Well, in &lt;a href="http://crossedlogic.blogspot.com/2008/09/group-by-time-timeserial-makes-return.html"&gt;Group By Time: TimeSerial Makes A Return To Microsoft SQL 2005&lt;/a&gt; we explored bringing TimeSerial functionality to SQL Server, but of course we can't stop there as the DateSerial function is pretty useful too.&lt;br /&gt;&lt;br /&gt;There are probably a number of different methods to achieve this, but here is what I came up with.&lt;br /&gt;&lt;br /&gt;Code listing:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; dbo.DateSerial(@&lt;span class="kwrd"&gt;year&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;, @&lt;span class="kwrd"&gt;month&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;, @&lt;span class="kwrd"&gt;day&lt;/span&gt; bigint)&lt;br /&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; datetime&lt;br /&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;date&lt;/span&gt; datetime&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- catch invalid year entries and default appropriately&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;year&lt;/span&gt; = &lt;span class="kwrd"&gt;CASE&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;WHEN&lt;/span&gt; @&lt;span class="kwrd"&gt;year&lt;/span&gt; &amp;lt; 1900 &lt;span class="kwrd"&gt;Then&lt;/span&gt; 1900&lt;br /&gt;        &lt;span class="kwrd"&gt;When&lt;/span&gt; @&lt;span class="kwrd"&gt;year&lt;/span&gt; &amp;gt; 9999 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="kwrd"&gt;year&lt;/span&gt;(getdate())&lt;br /&gt;        &lt;span class="kwrd"&gt;Else&lt;/span&gt; @&lt;span class="kwrd"&gt;year&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="rem"&gt;-- convert date by adding together like yyyymmdd&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;date&lt;/span&gt; = &lt;span class="kwrd"&gt;Cast&lt;/span&gt;(&lt;span class="kwrd"&gt;Cast&lt;/span&gt;(@&lt;span class="kwrd"&gt;year&lt;/span&gt; * 10000 + 101 &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;varchar&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; datetime)&lt;br /&gt;    &lt;span class="rem"&gt;-- Alternative method of parsing year into base date&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- SET @date = Cast('1/1/' + Cast(@year As varchar) As datetime)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- Add to date the proper months subtracting 1 since we used 1 as start instead of zero.    &lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;date&lt;/span&gt; = DateAdd(mm, @&lt;span class="kwrd"&gt;month&lt;/span&gt; - 1, @&lt;span class="kwrd"&gt;date&lt;/span&gt;)&lt;br /&gt;    &lt;span class="rem"&gt;-- Add to date the proper days subtracting 1 since we used 1 as start instead of zero.    &lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;date&lt;/span&gt; = DateAdd(dd, @&lt;span class="kwrd"&gt;day&lt;/span&gt; - 1, @&lt;span class="kwrd"&gt;date&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; @&lt;span class="kwrd"&gt;date&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;/pre&gt;First line is to avoid errors in incorrect starting year value, but can be adjusted according to your own needs. The months and days are added in through simple DateAdd which allows for positive/negative numbers in addition to not being bound by 12 or 31 respectively making this like our TimeSerial function in that it can be used to simply convert a year, month, and day into date or to do some date math on the fly.&lt;br /&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; dbo.DateSerial(&lt;span class="kwrd"&gt;YEAR&lt;/span&gt;(GETDATE()), &lt;span class="kwrd"&gt;MONTH&lt;/span&gt;(GETDATE()), 1 - 35) &lt;span class="kwrd"&gt;AS&lt;/span&gt; dateSerialized&lt;/pre&gt;This will return the date 35 days prior to the first day of the current month in the current year. Moreover, since this solution takes advantage of user defined function only, implementing in SQL 2000 should not be an issue.&lt;br /&gt;&lt;br /&gt;So there you have it, DateSerial in SQL Server.&lt;br /&gt;&lt;br /&gt;Happy coding!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/group-by-time-timeserial-makes-return.html"&gt;Group By Time: TimeSerial Makes A Return To Microsoft SQL 2005&lt;/a&gt; &lt;/li&gt;&lt;li&gt;DateSerial in Access: &lt;a href="http://office.microsoft.com/en-us/access/HA012288131033.aspx"&gt;http://office.microsoft.com/en-us/access/HA012288131033.aspx&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-139422875324231302?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/139422875324231302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=139422875324231302' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/139422875324231302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/139422875324231302'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/dateserial-in-microsoft-sql-server-2005.html' title='DateSerial In Microsoft SQL Server 2005'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-7689069551281277461</id><published>2008-09-07T13:31:00.008-04:00</published><updated>2008-09-08T21:28:54.294-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>Group By Time: TimeSerial Makes A Return To Microsoft SQL 2005</title><content type='html'>Last time we looked at grouping by time for our customer calls statistics by the half an hour. We ended with this code based on SQL 2005 common table expression syntax.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt; TableByTime &lt;span class="kwrd"&gt;As&lt;/span&gt; ( &lt;br /&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;Cast&lt;/span&gt;(DateName(hh, CallDateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Int&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; [Sort], &lt;br /&gt;        &lt;span class="kwrd"&gt;Right&lt;/span&gt;(&lt;span class="str"&gt;'0'&lt;/span&gt; + &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'12'&lt;/span&gt; &lt;br /&gt;        &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt;= 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; DateName(hh, CallDateTime) &lt;br /&gt;        &lt;span class="kwrd"&gt;Else&lt;/span&gt; DateName(hh, DateAdd(hh, -12, CallDateTime)) &lt;span class="kwrd"&gt;End&lt;/span&gt;,  2)  + &lt;span class="str"&gt;':'&lt;/span&gt; + &lt;br /&gt;        &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(n, CallDateTime) &amp;gt;= 30 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'30'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'00'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; +&lt;br /&gt;        &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt; 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'AM'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'PM'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;As&lt;/span&gt; [&lt;span class="kwrd"&gt;Hour&lt;/span&gt;], &lt;br /&gt;        Customer&lt;br /&gt;    &lt;span class="kwrd"&gt;FROM&lt;/span&gt; CustomerCalls (NoLock)&lt;br /&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;Hour&lt;/span&gt;,  &lt;span class="kwrd"&gt;Count&lt;/span&gt;(*)&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; TableByTime&lt;br /&gt;&lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Sort, &lt;span class="kwrd"&gt;Hour&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Sort, Hour&lt;/pre&gt;We can be satisfied with this, but why waste a perfectly good opportunity to keep learning. In all seriousness, breakdowns by date/time are statistics I often have to get, so if you are anything like me it would be good to explore making this more reusable and streamlined. Since what we have above is very clean compared to the starting point, what we have left to do is create a function to emulate the TimeSerial function from Microsoft Access that does what our case statements are doing and more.&lt;br /&gt;&lt;br /&gt;In summary, TimeSerial, takes in hour in military notation (i.e. 14 for 2PM), minutes, and seconds and translates to appropriate time in format hh:mm:ss with AM/PM indicator. In addition to straight time display, it could do calculations for you based on varying inputs and use of negatives. If you want more information on how TimeSerial functions, see reference for function in Microsoft Access below.&lt;br /&gt;&lt;br /&gt;So diving in, we can write a function like this that adds TimeSerial to Microsoft SQL Server using a user defined function.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; dbo.TimeSerial (@hrs &lt;span class="kwrd"&gt;int&lt;/span&gt;, @&lt;span class="kwrd"&gt;min&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;, @sec bigint)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; nvarchar(10)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;result&lt;/span&gt; nvarchar(10), @total bigint, @AMorPM nvarchar(2)&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @hours &lt;span class="kwrd"&gt;int&lt;/span&gt;, @minutes &lt;span class="kwrd"&gt;int&lt;/span&gt;, @seconds &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- convert everything to seconds handling null params with isnull or coalesce&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @total = IsNull(@sec,0) + IsNull(@&lt;span class="kwrd"&gt;min&lt;/span&gt;,0) * 60 + IsNull(@hrs,0) * 3600&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @total = 86400 + @total % 86400 &lt;span class="rem"&gt;-- handle negative time relative to midnight&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- calculate the hour portion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @hours = 0&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;IF&lt;/span&gt; (@total &amp;gt;= 3600)&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @hours = floor(@total/3600) % 24&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @total = @total % 3600&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- set am/pm based on hours in HH format&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @AMorPM = &lt;span class="str"&gt;'PM'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;IF&lt;/span&gt; @hours &amp;lt; 12&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @AMorPM = &lt;span class="str"&gt;'AM'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- adjust hours to non-military time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;IF&lt;/span&gt; @hours &amp;gt; 12 &lt;span class="kwrd"&gt;OR&lt;/span&gt; @hours = 0&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @hours = abs(@hours - 12)&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- calculate the minutes and seconds portion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @minutes = 0&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;IF&lt;/span&gt; (@total &amp;gt;= 60)&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @minutes = floor(@total/60)&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @total = @total % 60&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;-- set seconds to remainder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @seconds = @total&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;result&lt;/span&gt; = &lt;span class="kwrd"&gt;Cast&lt;/span&gt;(@hours &lt;span class="kwrd"&gt;As&lt;/span&gt; nvarchar(2)) + &lt;span class="str"&gt;':'&lt;/span&gt; + &lt;span class="kwrd"&gt;RIGHT&lt;/span&gt;(&lt;span class="str"&gt;'0'&lt;/span&gt;+&lt;span class="kwrd"&gt;Cast&lt;/span&gt;(@minutes &lt;span class="kwrd"&gt;As&lt;/span&gt; nvarchar(2)), 2)&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;result&lt;/span&gt; = @&lt;span class="kwrd"&gt;result&lt;/span&gt; + &lt;span class="str"&gt;':'&lt;/span&gt; + &lt;span class="kwrd"&gt;RIGHT&lt;/span&gt;(&lt;span class="str"&gt;'0'&lt;/span&gt;+&lt;span class="kwrd"&gt;Cast&lt;/span&gt;(@seconds &lt;span class="kwrd"&gt;As&lt;/span&gt; nvarchar(2)),2) + @AMorPM&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; @&lt;span class="kwrd"&gt;result&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    END&lt;/pre&gt;As you will see in the code above, which hopefully speaks for itself as to what it is doing, we can do a little more than just format our time so we abstract out the need for extensive case when logic and give ourselves a handy utility function for our SQL toolkit.&lt;br /&gt;&lt;br /&gt;Putting it in place with our original query, we can immediately simplify our syntax to this.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt; TableByTime &lt;span class="kwrd"&gt;As&lt;/span&gt; (&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;Cast&lt;/span&gt;(DateName(hh, CallDateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Int&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; [Hr],&lt;br /&gt;&lt;br /&gt;           FLOOR(&lt;span class="kwrd"&gt;Cast&lt;/span&gt;(DateName(n, CallDateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Int&lt;/span&gt;)/30) * 30 &lt;span class="kwrd"&gt;As&lt;/span&gt; [Mi],&lt;br /&gt;&lt;br /&gt;           Customer&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;FROM&lt;/span&gt; CustomerCalls (NoLock)&lt;br /&gt;&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;    dbo.TimeSerial(Hr, Mi, 0) &lt;span class="kwrd"&gt;As&lt;/span&gt; [&lt;span class="kwrd"&gt;Hour&lt;/span&gt;],&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Count&lt;/span&gt;(*)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; TableByTime&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Hr, Mi&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Hr, Mi&lt;/pre&gt;Aside from the TimeSerial function addition to the code, you will notice a better algorithm to get to group time in 30 minute buckets using floor which gets the lowest integer count of 30 in the number of minutes currently in our time. Since Microsoft SQL will typically do integer division on two numbers that are int datatypes this is probably unnecessary, but I like to be very deliberate in code for nothing else than I will remember what I was thinking when I look at it a year later. The premise here is that we will only ever get 0 or 1 from the division and then multiplying by 30 will give us the correct bucket.&lt;br /&gt;&lt;br /&gt;Well we are close to being golden, but we still have a little fluff just to extract the hour and minute portions of time as we have to get as string then cast, so we could write functions for those as well; however, with Microsoft SQL Server, you can utilize ODBC canonical functions for { fn HOUR() } and { fn MINUTE() }.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt; dbo.TimeSerial({ fn &lt;span class="kwrd"&gt;HOUR&lt;/span&gt;(GETDATE()) }, FLOOR({ fn &lt;span class="kwrd"&gt;MINUTE&lt;/span&gt;(GETDATE()) } / 30) * 30, 0) &lt;span class="kwrd"&gt;AS&lt;/span&gt; HourBucket&lt;/pre&gt;&lt;br /&gt;As you see above, in combination with our user defined function for TimeSerial the ODBC canonical functions for HOUR and MINUTE make it very streamlined to get our hour bucket in one statement.  For sorting purposes, it will probably still be a good idea to use the { fn HOUR() } in Hr column and { fn MINUTE() } in the Mi column in previous code using the common table expression we composed, then just use TimeSerial with those column values.&lt;br /&gt;&lt;br /&gt;In conclusion, combining the flexibility of user defined functions and some of the tools in our SQL toolkit with Microsoft SQL Server, we can keep the user community happy with snappy time based reports.  The common language runtime (CLR), which we didn't discuss here in detail, is another great means of adding user defined functionality.  Anyway, happy coding.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Original Post: &lt;a href="http://crossedlogic.blogspot.com/2008/09/group-by-time-microsoft-sql-server-2005.html"&gt;"Group By Time: The Microsoft SQL Server 2005 Way"&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Access TimeSerial: &lt;a href="http://office.microsoft.com/en-us/access/HA012289251033.aspx"&gt;http://office.microsoft.com/en-us/access/HA012289251033.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-7689069551281277461?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/7689069551281277461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=7689069551281277461' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7689069551281277461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7689069551281277461'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/group-by-time-timeserial-makes-return.html' title='Group By Time: TimeSerial Makes A Return To Microsoft SQL 2005'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-8744717879893454234</id><published>2008-09-06T03:48:00.003-04:00</published><updated>2008-09-13T13:51:56.780-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Range Searching Using Java</title><content type='html'>Welcome! Intrigued by my findings in my last post regarding &lt;a href="http://crossedlogic.blogspot.com/2008/09/range-searching-using-visual-basic-net.html"&gt;Range Searching Using Visual Basic .NET&lt;/a&gt;, I decided to try to reproduce the FindAll methodology as well as my binary search based on range for grins and again was surprised by my findings. Binary search worked the fastest/consistently within Java code where all three methods were faster which was not too much of a surprise other than the ported FindAll since it and the concept of Predicate match was not native (at least not to my knowledge) at the time of writing this post.&lt;br /&gt;&lt;br /&gt;Background summary for those that haven't read the original article in VB, this started as research based on a question of finding the dates within a list that match a selected date range. The intent was to go beyond the simple iteration and match method and find a faster means through binary search only to find the VB FindAll and Predicate implementation eluded to above and slower performance from binary range functions created.&lt;br /&gt;&lt;br /&gt;With that said, onward and upward!&lt;br /&gt;&lt;br /&gt;The journey in Java begins with replicating our utility class Ranges that handles the simple match method utilized by looping through array as well as our binary search implementation based on a start and end of a range.&lt;br /&gt;&lt;br /&gt;The code listing is below:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;package&lt;/span&gt; com.blogspot.crossedlogic.rangesearching;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Ranges {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; final &lt;span class="kwrd"&gt;int&lt;/span&gt; NOT_FOUND = -1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Binary search through a sorted array to determine first index &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * greater or equal to start of range. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param array&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param rangePoint&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @return integer index or (-1) when not found&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &amp;lt;T extends Comparable&amp;lt;T&amp;gt;&amp;gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; binaryStartOfRangeSearch(T[] array, T rangePoint) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; low = 0;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; high = array.length - 1;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; mid;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; comparedToHigh = rangePoint.compareTo(array[high]);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (comparedToHigh == 0) { &lt;span class="kwrd"&gt;return&lt;/span&gt; high; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (comparedToHigh &amp;lt; 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[low]) &amp;lt;= 0) { &lt;span class="kwrd"&gt;return&lt;/span&gt; low; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;while&lt;/span&gt; (low != high) {&lt;br /&gt;&lt;br /&gt;mid = (&lt;span class="kwrd"&gt;int&lt;/span&gt;)Math.floor((low + high) / 2);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[mid]) &amp;lt;= 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[mid - 1]) &amp;lt;= 0) {&lt;br /&gt;&lt;br /&gt;high = --mid;&lt;br /&gt;&lt;br /&gt;} &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; mid;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;} &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[mid + 1]) &amp;lt;= 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; ++mid;&lt;br /&gt;&lt;br /&gt;} &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;low = ++mid;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; NOT_FOUND;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Binary search through a sorted array to determine last index &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * lesser or equal to end of range. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param array&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param rangePoint&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @return integer index or (-1) when not found&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &amp;lt;T extends Comparable&amp;lt;T&amp;gt;&amp;gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; binaryEndOfRangeSearch(T[] array, T rangePoint) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; low = 0;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; high = array.length - 1;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; mid;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; comparedToLow = rangePoint.compareTo(array[low]);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (comparedToLow == 0) { &lt;span class="kwrd"&gt;return&lt;/span&gt; low; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (comparedToLow &amp;gt; 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[high]) &amp;gt;= 0) { &lt;span class="kwrd"&gt;return&lt;/span&gt; high; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;while&lt;/span&gt; (low != high) {&lt;br /&gt;&lt;br /&gt;mid = (&lt;span class="kwrd"&gt;int&lt;/span&gt;)Math.ceil((low + high) / 2);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[mid]) &amp;gt;= 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[mid + 1]) &amp;gt;= 0) {&lt;br /&gt;&lt;br /&gt;low = ++mid;&lt;br /&gt;&lt;br /&gt;} &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; mid;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;} &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (rangePoint.compareTo(array[mid - 1]) &amp;gt;= 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; --mid;&lt;br /&gt;&lt;br /&gt;} &lt;span class="kwrd"&gt;else&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;high = --mid;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; NOT_FOUND;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Check if an object falls within a specified range.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param c&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param rangeStart&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param rangeEnd&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &amp;lt;T extends Comparable&amp;lt;T&amp;gt;&amp;gt; boolean matchRange(T c, T rangeStart, T rangeEnd) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (c.compareTo(rangeStart) &amp;gt;= 0 &amp;amp;&amp;amp; c.compareTo(rangeEnd) &amp;lt; 1) { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;As stated in my last post, the use of generics expanded my research beyond Date types and provided a framework for searching different types as long as their range principals were the same as implemented and they implemented the Comparable interface. For more information on Generics, please see the reference(s) below; however, the matchRange function reads like this for example: taking in any type T denoted by the parameter c which implements the Comparable interface (T extends Comparable&lt;t&gt;) and two other instances of type T representing a start and end of a range, return a true or false flag indicating existence within range.&lt;br /&gt;&lt;br /&gt;Comparable interface is used the same here as the compareTo function has the same usage and return values (at least in typical implementations of primitive/standard types): -1 when first object is smaller than the one being compared to; 0, the two equal; 1, first is larger.&lt;br /&gt;&lt;br /&gt;As you will see, the usage of these functions are virtually the same from VB implementation:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;// simple loop and match method&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (String s : arrayOfObjects) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (Ranges.matchRange(s, RANGE_START, RANGE_END)) {&lt;br /&gt;&lt;br /&gt;lst.add(s);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;// binary range search method&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Arrays.sort(arrayOfObjects);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; idxStart = Ranges.binaryEndOfRangeSearch(&lt;br /&gt;&lt;br /&gt;arrayOfObjects, RANGE_START);&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; idxEnd = Ranges.binaryEndOfRangeSearch(&lt;br /&gt;&lt;br /&gt;arrayOfObjects, RANGE_END);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (idxStart &amp;gt;= 0 &amp;amp;&amp;amp; idxEnd &amp;gt;= 0) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = idxStart; i &amp;lt;= idxEnd; i++) {&lt;br /&gt;&lt;br /&gt;lst.add(arrayOfObjects[i]);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;What will be a little different is the FindAll implementation as this was done using some non-native interfaces similar to methodology discussed in the reference section from faqs{dot}com. To get the same functionality, an interface for Predicate had to be added. In addition, a Predicates class was created that implemented a FindAll equivalent that requires an implemented Predicate to return a matching List of objects. Then using Java's anonymous class syntax, we implement Predicate's required match function as we would with delegate.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Predicate interface used to emulate .NET &amp;lt;code&amp;gt;System.Predicate(Of T)&amp;lt;/code&amp;gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;package&lt;/span&gt; com.blogspot.crossedlogic.rangesearching;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; Predicate&amp;lt;T&amp;gt; {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param object to test against predicate criteria.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @return boolean flag indicating a match (true) or no match (false).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; boolean isMatch(T obj);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Predicates class containing static implementation of FindAll.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;package&lt;/span&gt; com.blogspot.crossedlogic.rangesearching;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Predicates {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * Replicate .NET findAll and &amp;lt;code&amp;gt;Predicate&amp;lt;/code&amp;gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param &amp;lt;T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param array&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @param match implementation of the Predicate interface.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; * @see com.blogspot.crossedlogic.rangesearching.Predicate&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt; */&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &amp;lt;T&amp;gt; List&amp;lt;T&amp;gt; findAll(T[] array, Predicate&amp;lt;T&amp;gt; match) {&lt;br /&gt;&lt;br /&gt;List&amp;lt;T&amp;gt; lst = &lt;span class="kwrd"&gt;new&lt;/span&gt; ArrayList&amp;lt;T&amp;gt;();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (T obj : array) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (match.isMatch(obj)) { lst.add(obj); }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; lst;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;// Example usage of FindAll for range searching.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;lst.addAll(Predicates.findAll(arrayOfObjects,&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;new&lt;/span&gt; Predicate&amp;lt;String&amp;gt;() {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; boolean isMatch(String s) {&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; Ranges.matchRange(s, RANGE_START, RANGE_END);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}));&lt;/pre&gt;&lt;br /&gt;Not one line, but it is just one code statement as the solution is to utilize the range add capabilities of the List interface couples with the List response of the findAll function using a Predicate which again we implement as a simple call to our static matchRange function coupled with constants for start and end of range.&lt;br /&gt;&lt;br /&gt;Well, I have kept you waiting long enough, here is how the results stack up:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by going through each item&lt;br /&gt;&lt;br /&gt;End processing: 37ms - 9311&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;&lt;br /&gt;End processing: 36ms - 9311&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;&lt;br /&gt;End processing: 14ms - 9311&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by going through each item&lt;br /&gt;&lt;br /&gt;End processing: 1ms - 9311&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;&lt;br /&gt;End processing: 3ms - 9311&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;&lt;br /&gt;End processing: 2ms - 9311&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by going through each item&lt;br /&gt;&lt;br /&gt;End processing: 1ms - 9312&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;&lt;br /&gt;End processing: 3ms - 9312&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;&lt;br /&gt;End processing: 2ms - 9312&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by going through each item&lt;br /&gt;&lt;br /&gt;End processing: 1ms - 9313&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;&lt;br /&gt;End processing: 3ms - 9313&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;&lt;br /&gt;End processing: 3ms - 9313&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by going through each item&lt;br /&gt;&lt;br /&gt;End processing: 2ms - 9314&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;&lt;br /&gt;End processing: 2ms - 9314&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;&lt;br /&gt;End processing: 3ms - 9314&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;/pre&gt;&lt;br /&gt;Aside from the first iteration where the static objects are created for the first time, you will see 1-3 millisecond (ms) response time from each of the three methodologies giving us two other tools in the toolkit for searching arrays/lists when dealing with large number of elements and ranges.&lt;br /&gt;&lt;br /&gt;I am glad I took this journey on the VB.NET side as it inspired me to want to explore this in Java and I am very pleased with the results. Hopefully, it will be useful for you in your travels as well and thanks for reading. We covered a lot of different ground in Generics, Predicates, sorting Arrays, binary search algorithm, and so on so please use links for more information on things I didn't go into details on including previous post as I may have glossed over something I discussed further there.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Thanks and remember to keep learning and/or keep smiling; you never want to end up a sad fool!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Source code: &lt;/strong&gt;&lt;a href="http://crossedlogic.abdu-shahid.com/java/com.blogspot.crossedlogic.rangesearching.zip"&gt;Download com.blogspot.crossedlogic.rangesearching.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://crossedlogic.blogspot.com/2008/09/range-searching-using-visual-basic-net.html"&gt;Range Searching Using Visual Basic .NET&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Generics in Java: &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html"&gt;http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Predicate in Java: &lt;a href="http://www.faqs.org/docs/javap/c12/ex-12-4-answer.html"&gt;http://www.faqs.org/docs/javap/c12/ex-12-4-answer.html&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Java does have a native &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/rowset/Predicate.html"&gt;Predicate interface&lt;/a&gt; under the javax.sql.rowset package, but, since not same as .NET predicate in our context, custom Predicate was used above.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-8744717879893454234?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/8744717879893454234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=8744717879893454234' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8744717879893454234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/8744717879893454234'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/range-searching-using-java.html' title='Range Searching Using Java'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-6240889562504840173</id><published>2008-09-05T03:40:00.002-04:00</published><updated>2008-09-13T12:25:12.033-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Range Searching Using Visual Basic .NET</title><content type='html'>The other day, I was asked a question about comparing dates in an array to a date range. The basic answer is to iterate through the array and compare each date to the beginning and ending of the range; however, with some curiosity exacerbated by another question planting the seed of binary searches in my head, I was determined to write a binary search algorithm for determining a value in a range. Along the way, I was enlightened/awoken to the concept of predicates in VB.NET and the System.Array.FindAll method. So this post will try to provide an overview of how to perform some range searching in .NET as I took research a step further and abstracted functionality to be more generic than with Date types.&lt;br /&gt;&lt;br /&gt;With that said, here is the basic comparison to any range of objects that implement the IComparable interface. &lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; MatchRange(Of T &lt;span class="kwrd"&gt;As&lt;/span&gt; IComparable)(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; c &lt;span class="kwrd"&gt;As&lt;/span&gt; T, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; rangeStart &lt;span class="kwrd"&gt;As&lt;/span&gt; T, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; rangeEnd &lt;span class="kwrd"&gt;As&lt;/span&gt; T) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;If&lt;/span&gt; c.CompareTo(rangeStart) &amp;gt;= 0 &lt;span class="kwrd"&gt;And&lt;/span&gt; c.CompareTo(rangeEnd) &amp;lt; 1 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;True&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;False&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;As long as you are comfortable with generics, the above is pretty straight forward (for more details on generics, see MSDN link in references) as we can now pass in any class that implements IComparable and take advantage of the public interface method CompareTo(Object) which will return one the following values: -1 when first object is smaller than the one being compared to; 0, the two equal; 1, first is larger. An easy demonstration of how this is used is MatchRange(5, 1, 10) will return true. So for back to original scenario of needing to determine all the values of a list that fall within a range, we get code like the following:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; lst &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)()&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; &lt;span class="kwrd"&gt;In&lt;/span&gt; arrayOfObjects&lt;br /&gt;    &lt;span class="kwrd"&gt;If&lt;/span&gt; Ranges.MatchRange(s, RANGE_START, RANGE_END) &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;        lst.Add(s)&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;Next&lt;/pre&gt;Where Ranges is the name of utility class I placed my Public Shared Function MatchRange and RANGE_START and RANGE_END are string constants representing the beginning and ending value of the range we are searching within.&lt;br /&gt;&lt;br /&gt;Speaking of the Ranges class, here is its full listing to dive right into the next step which was to implement a better range search using binary search algorithm:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Option&lt;/span&gt; Explicit &lt;span class="kwrd"&gt;On&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Option&lt;/span&gt; Strict &lt;span class="kwrd"&gt;On&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Namespace&lt;/span&gt; CrossedLogic.BlogSport.RangeSearching&lt;br /&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; Ranges&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' Binary search through a sorted array to determine first index &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' greater or equal to start of range.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="array"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="rangePoint"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;returns&amp;gt;integer index or (-1) when not found&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; BinaryStartOfRangeSearch(Of T &lt;span class="kwrd"&gt;As&lt;/span&gt; IComparable)(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; array &lt;span class="kwrd"&gt;As&lt;/span&gt; T(), &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; rangePoint &lt;span class="kwrd"&gt;As&lt;/span&gt; T) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; low &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; high &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = array.Length - 1&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; mid &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; startComparedToHigh &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = rangePoint.CompareTo(array(high))&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;If&lt;/span&gt; startComparedToHigh = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;Return&lt;/span&gt; high&lt;br /&gt;            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;If&lt;/span&gt; startComparedToHigh &amp;lt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(low)) &amp;lt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;Return&lt;/span&gt; low&lt;br /&gt;                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;While&lt;/span&gt; low &amp;lt;&amp;gt; high&lt;br /&gt;                    mid = &lt;span class="kwrd"&gt;CInt&lt;/span&gt;(Math.Floor((low + high) / 2))&lt;br /&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(mid)) &amp;lt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                        &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(mid - 1)) &amp;lt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                            high = mid - 1&lt;br /&gt;                        &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;br /&gt;                            &lt;span class="kwrd"&gt;Return&lt;/span&gt; mid&lt;br /&gt;                        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;br /&gt;                        &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(mid + 1)) &amp;lt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                            &lt;span class="kwrd"&gt;Return&lt;/span&gt; mid + 1&lt;br /&gt;                        &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;br /&gt;                            low = mid + 1&lt;br /&gt;                        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;While&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Return&lt;/span&gt; -1&lt;br /&gt;        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' Binary search through a sorted array to determine last index &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' lesser or equal to end of range.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="array"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="rangePoint"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;returns&amp;gt;integer index or (-1) when not found&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; BinaryEndOfRangeSearch(Of T &lt;span class="kwrd"&gt;As&lt;/span&gt; IComparable)(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; array &lt;span class="kwrd"&gt;As&lt;/span&gt; T(), &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; rangePoint &lt;span class="kwrd"&gt;As&lt;/span&gt; T) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; low &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; high &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = array.Length - 1&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; mid &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; endComparedToLow &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = rangePoint.CompareTo(array(low))&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;If&lt;/span&gt; endComparedToLow = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;Return&lt;/span&gt; low&lt;br /&gt;            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;If&lt;/span&gt; endComparedToLow &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(high)) &amp;gt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;Return&lt;/span&gt; high&lt;br /&gt;                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;While&lt;/span&gt; low &amp;lt;&amp;gt; high&lt;br /&gt;                    mid = &lt;span class="kwrd"&gt;CInt&lt;/span&gt;(Math.Ceiling((low + high) / 2))&lt;br /&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(mid)) &amp;gt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                        &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(mid + 1)) &amp;gt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                            low = mid + 1&lt;br /&gt;                        &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;br /&gt;                            &lt;span class="kwrd"&gt;Return&lt;/span&gt; mid&lt;br /&gt;                        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;br /&gt;                        &lt;span class="kwrd"&gt;If&lt;/span&gt; rangePoint.CompareTo(array(mid - 1)) &amp;gt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                            &lt;span class="kwrd"&gt;Return&lt;/span&gt; mid - 1&lt;br /&gt;                        &lt;span class="kwrd"&gt;Else&lt;/span&gt;&lt;br /&gt;                            high = mid - 1&lt;br /&gt;                        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;While&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Return&lt;/span&gt; -1&lt;br /&gt;        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' Check if an object falls within a specified range.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="c"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="rangeStart"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;param name="rangeEnd"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; MatchRange(Of T &lt;span class="kwrd"&gt;As&lt;/span&gt; IComparable)(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; c &lt;span class="kwrd"&gt;As&lt;/span&gt; T, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; rangeStart &lt;span class="kwrd"&gt;As&lt;/span&gt; T, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; rangeEnd &lt;span class="kwrd"&gt;As&lt;/span&gt; T) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;If&lt;/span&gt; c.CompareTo(rangeStart) &amp;gt;= 0 &lt;span class="kwrd"&gt;And&lt;/span&gt; c.CompareTo(rangeEnd) &amp;lt; 1 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;True&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;False&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; Namespace&lt;/pre&gt;And its usage:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; lst &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; List(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)()&lt;br /&gt;&lt;br /&gt;System.Array.Sort(arrayOfObjects)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; idxStart &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = Ranges.BinaryStartOfRangeSearch(arrayOfObjects, RANGE_START)&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; idxEnd &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = Ranges.BinaryEndOfRangeSearch(arrayOfObjects, RANGE_END)&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;If&lt;/span&gt; idxStart &amp;gt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;If&lt;/span&gt; idxEnd &amp;lt; idxStart &lt;span class="kwrd"&gt;Then&lt;/span&gt; idxEnd = arrayOfObjects.Length - 1&lt;br /&gt;    &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = idxStart &lt;span class="kwrd"&gt;To&lt;/span&gt; idxEnd&lt;br /&gt;        lst.Add(arrayOfObjects(i))&lt;br /&gt;    &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; If&lt;/pre&gt;First difference, you should see is that like regular binary search, the array must be sorted. Once we have a sorted array, we can use our binary search functions specific to beginning and ending of the range to get the respective index. Using the indices, we can add just those objects to the list we created to store results. Well a bit more code, but well worth it for the end game of faster searches of large object arrays like the example 13,149 string array used in the research for this post. Consequently, though, to my surprise, this code did not run faster mostly because of the requirement for sorting. With the original date question, even the initial solution above was sorted using System.Array.Sort; however, since that solution will yield the same list just unordered, for the sake of performance measurement I left array unsorted and then sorted as part of the binary search method.&lt;br /&gt;&lt;br /&gt;Here are some of the results to illustrate difference:&lt;pre class="csharpcode"&gt;&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by going through each item&lt;br /&gt;End processing: 110ms - 9311&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;End processing: 13ms - 9311&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;End processing: 59ms - 9311&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by going through each item&lt;br /&gt;End processing: 6ms - 9311&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;End processing: 14ms - 9311&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;End processing: 47ms - 9311&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by going through each item&lt;br /&gt;End processing: 10ms - 9312&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;End processing: 8ms - 9312&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;End processing: 50ms - 9312&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by going through each item&lt;br /&gt;End processing: 6ms - 9313&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;End processing: 8ms - 9313&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;End processing: 51ms - 9313&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by going through each item&lt;br /&gt;End processing: 6ms - 9314&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by using FindAll.&lt;br /&gt;End processing: 8ms - 9314&lt;br /&gt;---------------------------------------------------&lt;br /&gt;Start processing by binary range search.&lt;br /&gt;End processing: 55ms - 9314&lt;br /&gt;---------------------------------------------------&lt;/pre&gt;&lt;br /&gt;As you will see above, the find by simple iteration of the array usually came in lower than the binary search method, although they both fluctuate, especially the simple loop method as it at times takes 100+ milliseconds (ms) while at others only 10 ms or below. Subsequently, you will notice that the FindAll although a few ms slower at times is very consistent and I found gives similar results regardless of the type of object in array whereas the other two vary as previously stated. So what is this FindAll method and how do I use it?&lt;br /&gt;&lt;br /&gt;Well the FindAll method is a public shared function within System.Array. It's usage is not only the most consistent, but as you will see the most streamlined aside from delegate function you have to create. Here is a listing assuming availability of previously posted code:&lt;pre class="csharpcode"&gt;&lt;br /&gt;lst.AddRange(System.Array.FindAll(arrayOfObjects, &lt;span class="kwrd"&gt;New&lt;/span&gt; Predicate(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; MatchRange)))&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;'Delegate implementation for Predicate needed in System.Array.FindAll&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; MatchRange(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; n &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Return&lt;/span&gt; Ranges.MatchRange(n, RANGE_START, RANGE_END)&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;Yes! One line is all, you are not reading that incorrectly. Taking advantage of the List's AddRange capabilities that will add all elements of an array to list and the FindAll implementation that will return an array of elements from the array argument that match our range through use of the Predicate(Of T) delegate implemented here by a local MatchRange function that takes type T which is String in this case and does logic to respond true or false for a match. Since I have already gone through the work of coding a functioning match range routine, our Predicate simply becomes a call to our shared MatchRange function.&lt;br /&gt;&lt;br /&gt;The one caveat to note with this solution is that since it only takes in object to be matched, the criteria and variables needed have to exist globally or just within this function which you can observe by my having to use RANGE_START and RANGE_END constants in my match. Moreover, if you are already using List(Of T) versus and array, you can simply utilize FindAll function of List to get a subset List(Of T). See references for more on the List.FindAll method.&lt;br /&gt;&lt;br /&gt;Well hopefully you have enjoyed this journey.&lt;br /&gt;&lt;br /&gt;In summary, you can most definitely use binary search method for primitives and possibly some types, but for Dates and Strings the System.Array.FindAll/List.FindAll are good utilities for large collections and the simple but effective for each loop and comparison.&lt;br /&gt;&lt;br /&gt;Happy coding!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="http://crossedlogic.abdu-shahid.com/vb/CrossedLogic.BlogSpot.RangeSearching.zip"&gt;Download CrossedLogic.BlogSpot.RangeSearching.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Generics in .NET: &lt;a href="http://msdn.microsoft.com/en-us/library/aa479866.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa479866.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Predicate in .NET: &lt;a href="http://msdn.microsoft.com/en-us/library/bfcke1bz.aspx"&gt;http://msdn.microsoft.com/en-us/library/bfcke1bz.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;List.FindAll: &lt;a href="http://msdn.microsoft.com/en-us/library/fh1w7y8z(VS.80).aspx"&gt;http://msdn.microsoft.com/en-us/library/fh1w7y8z(VS.80).aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-6240889562504840173?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/6240889562504840173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=6240889562504840173' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/6240889562504840173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/6240889562504840173'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/range-searching-using-visual-basic-net.html' title='Range Searching Using Visual Basic .NET'/><author><name>theblackknight</name><uri>http://www.blogger.com/profile/01992642988268783007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/-N9Tpnx68ylg/TVwffUGQ9SI/AAAAAAAAAAQ/mU3d2O6EYD0/s220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-390277718641198804</id><published>2008-09-04T17:07:00.010-04:00</published><updated>2008-09-07T13:30:17.080-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>Group By Time: The Microsoft SQL Server 2005 Way</title><content type='html'>Statistics, we all seem to need them, but it is not always easy getting them exactly the way you would like. This article is going to explore the simple task of grouping data by hour spiced up a bit by displaying results in standard time format with AM/PM instead of military time and groupings every 30 minutes.&lt;br /&gt;Say you have the following data.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Table: CustomerCalls &lt;/strong&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5242282127932574114" style="CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_OhPQeKhdpOA/SMBT0g_MyaI/AAAAAAAAABU/jKRTpzNey0Y/s400/CustomerCallsTable.jpg" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Desired Report&lt;/strong&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5242282742192932658" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_OhPQeKhdpOA/SMBUYRSSBzI/AAAAAAAAABc/KaV0rMph4hg/s400/DesiredReport.jpg" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Starting with the basics, we do the following:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; DateName(hh, CallDateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; [&lt;span class="kwrd"&gt;Hour&lt;/span&gt;], &lt;span class="kwrd"&gt;Count&lt;/span&gt;(*) &lt;span class="kwrd"&gt;As&lt;/span&gt; [Calls]&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; CustomerCalls&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; DateName(hh, CallDateTime) &lt;/pre&gt;&lt;br /&gt;Using the DateName function, we grab the hour portion of &lt;em&gt;datetime&lt;/em&gt; column in our table and group rows and count. All is well and we get results like this by military time hour of the day:&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5242283381698776002" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_OhPQeKhdpOA/SMBU9foWy8I/AAAAAAAAABk/7iFZNQHL73Y/s400/Results1.jpg" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Great! But now we need to put in a little bit of fancy formatting to change 0100 to 01:00AM for the non-combat oriented among us.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;     &lt;span class="kwrd"&gt;Right&lt;/span&gt;(&lt;span class="str"&gt;'0'&lt;/span&gt; + &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'12'&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt;= 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; DateName(hh, CallDateTime)&lt;br /&gt;    &lt;span class="kwrd"&gt;Else&lt;/span&gt; DateName(hh, DateAdd(hh, -12, CallDateTime)) &lt;span class="kwrd"&gt;End&lt;/span&gt;, 2) + &lt;span class="str"&gt;':'&lt;/span&gt; +&lt;br /&gt;    &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(n, CallDateTime) &amp;gt;= 30 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'30'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'00'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; +&lt;br /&gt;    &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt; 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'AM'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'PM'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;As&lt;/span&gt; [&lt;span class="kwrd"&gt;Hour&lt;/span&gt;],&lt;br /&gt;    &lt;span class="kwrd"&gt;Count&lt;/span&gt;(*) &lt;span class="kwrd"&gt;As&lt;/span&gt; [Calls]&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; CustomerCalls(NoLock)&lt;br /&gt;&lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; &lt;span class="kwrd"&gt;Right&lt;/span&gt;(&lt;span class="str"&gt;'0'&lt;/span&gt; + &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'12'&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt;= 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; DateName(hh, CallDateTime)&lt;br /&gt;    &lt;span class="kwrd"&gt;Else&lt;/span&gt; DateName(hh, DateAdd(hh, -12, CallDateTime)) &lt;span class="kwrd"&gt;End&lt;/span&gt;, 2) + &lt;span class="str"&gt;':'&lt;/span&gt; +&lt;br /&gt;    &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(n, CallDateTime) &amp;gt;= 30 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'30'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'00'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; +&lt;br /&gt;    &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt; 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'AM'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'PM'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Life is all well and good again. Well maybe. That code is crazy as we must have the entire case logic in the group by statement to not violate SQL syntax rules when grouping, so what to do next. Well good news for us there is the WITH statement in SQL Server 2005 for creating Common Table Expressions (CTE). So diving into CTE, the code all together including some added functionality to sort in correct time of day order is below:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;WITH&lt;/span&gt; TableByTime &lt;span class="kwrd"&gt;As&lt;/span&gt; (&lt;br /&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;Cast&lt;/span&gt;(DateName(hh, CallDateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Int&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; [Sort],&lt;br /&gt;    &lt;span class="kwrd"&gt;Right&lt;/span&gt;(&lt;span class="str"&gt;'0'&lt;/span&gt; + &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'12'&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt;= 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; DateName(hh, CallDateTime)&lt;br /&gt;    &lt;span class="kwrd"&gt;Else&lt;/span&gt; DateName(hh, DateAdd(hh, -12, CallDateTime)) &lt;span class="kwrd"&gt;End&lt;/span&gt;,  2)  + &lt;span class="str"&gt;':'&lt;/span&gt; +&lt;br /&gt;    &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(n, CallDateTime) &amp;gt;= 30 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'30'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'00'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; +&lt;br /&gt;    &lt;span class="kwrd"&gt;Case&lt;/span&gt; &lt;span class="kwrd"&gt;When&lt;/span&gt; DateName(hh, CallDateTime) &amp;lt; 12 &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="str"&gt;'AM'&lt;/span&gt; &lt;span class="kwrd"&gt;Else&lt;/span&gt; &lt;span class="str"&gt;'PM'&lt;/span&gt; &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;As&lt;/span&gt; [&lt;span class="kwrd"&gt;Hour&lt;/span&gt;],&lt;br /&gt;    Customer&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; CustomerCalls (NoLock)&lt;br /&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;Hour&lt;/span&gt;,  &lt;span class="kwrd"&gt;Count&lt;/span&gt;(*)&lt;br /&gt;&lt;span class="kwrd"&gt;FROM&lt;/span&gt; TableByTime&lt;br /&gt;&lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Sort, &lt;span class="kwrd"&gt;Hour&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; Sort, &lt;span class="kwrd"&gt;Hour&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Wonderful! And code is not too unmanageable in my humble opinion. Probably can break it down some more, but as you see the benefits of CTE has already improved readability that I stopped here for implementation.&lt;br /&gt;&lt;br /&gt;Let’s take a deeper look at the code since we glossed over this earlier. First column takes the normal military hour ensuring it is functioning as an integer for use as our sorting mechanism later since time in military notation goes from 0 – 23 which is nicely ordered for us already. Second column, [Hour], is our case when breaking down datetime column to standard time of day: 12:00AM – 11:30PM as we also group the times within the first and last 30 minutes of each hour. The third column (could be columns) is data we want from the table – used Customer which we didn’t really need for our aggregate which is only a count; however, if we were doing sums or other statistical analysis on numerical data in the CustomerCalls table we could add those columns here.&lt;br /&gt;&lt;br /&gt;Now that we have our CTE, you can see the subsequent T-SQL statement where we actually implement the GROUP BY statement is drastically simplified as we have [Hour] column to call directly instead of the entire case logic. We ORDER BY our sort column and then by our hour and presto we have our results.&lt;br /&gt;&lt;br /&gt;In conclusion, using Common Table Expressions in SQL Server 2005 adds a great deal of power and flexibility beyond my simple case here while streamlining SQL statements to be easier to maintain/read, so read up and enjoy the cool new features of Microsoft SQL Server.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;WITH common_table_expression: &lt;a href="http://msdn.microsoft.com/en-us/library/ms175972(SQL.90).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms175972(SQL.90).aspx&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DateName function: &lt;a href="http://msdn.microsoft.com/en-us/library/ms174395.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms174395.aspx&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-390277718641198804?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/390277718641198804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=390277718641198804' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/390277718641198804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/390277718641198804'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/group-by-time-microsoft-sql-server-2005.html' title='Group By Time: The Microsoft SQL Server 2005 Way'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_OhPQeKhdpOA/SMBT0g_MyaI/AAAAAAAAABU/jKRTpzNey0Y/s72-c/CustomerCallsTable.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-4116621772117119404</id><published>2008-09-01T21:40:00.002-04:00</published><updated>2008-09-15T16:47:57.214-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user defined functions'/><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>Converting Delimited String To Separate Values In SQL</title><content type='html'>Ever need to split a comma delimited string for use in SQL? If so, this post will go through a simple Microsoft SQL Server 2005 example of converting delimited text to a SQL table variable.&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; [dbo].[split] (@csv nvarchar(&lt;span class="kwrd"&gt;max&lt;/span&gt;), @delim &lt;span class="kwrd"&gt;varchar&lt;/span&gt;(1))&lt;br /&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; @entries &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; (entry nvarchar(100))&lt;br /&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @commaindex &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @commaindex = CHARINDEX(@delim, @csv)&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;IF&lt;/span&gt; @commaindex &amp;gt; 0&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; @entries&lt;br /&gt;            &lt;span class="rem"&gt;-- insert left side&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; LTrim(RTrim(&lt;span class="kwrd"&gt;LEFT&lt;/span&gt;(@csv, @commaindex-1)))&lt;br /&gt;            &lt;span class="rem"&gt;-- pass right side recursively&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;UNION&lt;/span&gt; &lt;span class="kwrd"&gt;ALL&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; entry&lt;br /&gt;            &lt;span class="kwrd"&gt;FROM&lt;/span&gt; dbo.split(&lt;span class="kwrd"&gt;RIGHT&lt;/span&gt;(@csv, LEN(@csv) - @commaindex), @delim)   &lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;ELSE&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; @entries&lt;br /&gt;            &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; LTrim(RTrim(@csv))&lt;br /&gt;        &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt;&lt;br /&gt;END&lt;/pre&gt;The above can be manipulated according to individual need as each entry may need to be more than a 100 character string or you may have a delimiter greater than one character. The key to this solution is the simplicity achieved through use of recursion. Instead of trying to parse through each position that delimiter could be in string from beginning to end, simply keep taking left portion off and passing right portion for further processing.&lt;br /&gt;&lt;br /&gt;To take a string and get distinct values, the UNION ALL statement can be changed to UNION or simply select distinct in usage of function which is pretty straight forward as well.&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;SELECT DISTINCT&lt;/span&gt; entry &lt;span class="kwrd"&gt;FROM&lt;/span&gt; dbo.split(&lt;span class="str"&gt;'my;delimited;text;to;be;parsed'&lt;/span&gt;, &lt;span class="str"&gt;';'&lt;/span&gt;)&lt;/pre&gt;As you can see, the string doesn't have to be comma delimited either.&lt;br /&gt;&lt;br /&gt;Of course this solution is very basic, but hopefully demonstrates some of the power of using user defined functions and recursion as a part of your SQL toolkit. Well keep learning and keep smiling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-4116621772117119404?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/4116621772117119404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=4116621772117119404' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/4116621772117119404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/4116621772117119404'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/09/converting-delimited-string-to-separate.html' title='Converting Delimited String To Separate Values In SQL'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-9057567019169623779</id><published>2008-01-28T22:13:00.001-05:00</published><updated>2008-09-13T09:58:15.018-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Cross-Site Exploitation Presentation</title><content type='html'>August 2007 presentation at the OISF meeting in Dayton OH.&lt;br /&gt;&lt;br /&gt;{content/link moved to newly created presentations segment of the side bar.}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-9057567019169623779?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/9057567019169623779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=9057567019169623779' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/9057567019169623779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/9057567019169623779'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2008/01/cross-site-exploitation-presentation.html' title='Cross-Site Exploitation Presentation'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-7934851125868288461</id><published>2007-09-14T22:43:00.000-04:00</published><updated>2008-09-13T09:40:08.993-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coldfusion'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Free ColdFusion Server</title><content type='html'>Since I have let the cat out of the bag that I am a bit of a Java enthusiast, I may as well admit to being a fan of ColdFusion which integrates with Java real well. You can use object-oriented constructs in ColdFusion as well as use Java to extend functionality or provide framework that can be executed easily from the web interface.&lt;br /&gt;&lt;br /&gt;Anyway, I just saw that New Atlanta released a new version of their ColdFusion server which is free. There are some restrictions on tag support that can be overcome by buying their full blown version with J2EE capabilities or Adobe's ColdFusion server.&lt;br /&gt;&lt;br /&gt;Either choice, one good point is that ColdFusion and Java integrate real well to allow designers use to the web interface niceties of ColdFusion Markup Language (CFML) while leveraging business logic code written in Java.&lt;br /&gt;&lt;br /&gt;For example you can create a normal Java class as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;package&lt;/span&gt; com.mydomain;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyClass {&lt;br /&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; getInt(){ &lt;span class="kwrd"&gt;return&lt;/span&gt; 1; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Then you can create and use the object in CF through a few tags:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cfset&lt;/span&gt; &lt;span class="attr"&gt;mc&lt;/span&gt; = &lt;span class="attr"&gt;createObject&lt;/span&gt;(&lt;span class="kwrd"&gt;"java"&lt;/span&gt;,&lt;span class="kwrd"&gt;"com.mydomain.MyClass"&lt;/span&gt;) &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;cfset&lt;/span&gt; &lt;span class="attr"&gt;myint&lt;/span&gt; = &lt;span class="attr"&gt;mc&lt;/span&gt;.&lt;span class="attr"&gt;getInt&lt;/span&gt;() &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;CFScript can be pretty useful in making this flow similar to syntax from Java itself, but using the CF tags aren't a bad way to go either especially if the point is separating duties between developers use to Java code and database design from web designers use to HTML style.&lt;br /&gt;&lt;br /&gt;Happy coding!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-7934851125868288461?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/7934851125868288461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=7934851125868288461' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7934851125868288461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/7934851125868288461'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/free-coldfusion-server.html' title='Free ColdFusion Server'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-4342156870753328351</id><published>2007-09-06T23:15:00.000-04:00</published><updated>2007-09-07T07:18:20.631-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='j#'/><title type='text'>Concurrent Threading Series (J# Revisited)</title><content type='html'>After discussing the .NET approach to threading and asynchronous processing, I figured I would circle back to my goal of showing in J# how threading would be accomplished in the same manner it was in our Java application example. Here is what the code looks like (mostly from the different Microsoft references on MSDN web-site. The interesting thing I found is that the use of IAsyncResult is slightly different in Jsharp and requires the use of an additional object System.Runtime.Remoting.Messaging.AsyncResult.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; System.Threading.ThreadPool;&lt;br /&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; System.Threading.WaitHandle;&lt;br /&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; System.Runtime.Remoting.Messaging.AsyncResult;&lt;br /&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; System.IAsyncResult;&lt;br /&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; System.AsyncCallback;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/** @delegate */&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; String taskDelegate(String x);&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Example&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; NUM_THRDS_CONCURRENT = 60;&lt;br /&gt;    &lt;span class="rem"&gt;/** &lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;     * Initializations to be done only once by application&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;     * Setup thread pool globally.&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;     */&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; workerThreads = 0, completionPortThreads = 0;&lt;br /&gt;        ThreadPool.GetMaxThreads(workerThreads, completionPortThreads);&lt;br /&gt;        &lt;span class="rem"&gt;//If current pool size is less than our maximum, change the pool size&lt;/span&gt;&lt;br /&gt;        boolean changePoolSize = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (workerThreads &amp;lt; NUM_THRDS_CONCURRENT)&lt;br /&gt;        {&lt;br /&gt;            workerThreads = NUM_THRDS_CONCURRENT;&lt;br /&gt;            changePoolSize = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (completionPortThreads &amp;lt; NUM_THRDS_CONCURRENT)&lt;br /&gt;        {&lt;br /&gt;            completionPortThreads = NUM_THRDS_CONCURRENT;&lt;br /&gt;            changePoolSize = &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (changePoolSize) ThreadPool.SetMaxThreads(workerThreads, completionPortThreads);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Example()&lt;br /&gt;    {&lt;br /&gt;        super();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; main() {&lt;br /&gt;        Example instance = &lt;span class="kwrd"&gt;new&lt;/span&gt; Example();&lt;br /&gt;        System.&lt;span class="kwrd"&gt;out&lt;/span&gt;.println(&lt;span class="str"&gt;"Processing started "&lt;/span&gt; + System.DateTime.get_Now().ToString());&lt;br /&gt;        instance.execute();&lt;br /&gt;        instance = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; execute()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; NUM_THRDS = 100;&lt;br /&gt;        taskDelegate tasks[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; taskDelegate[NUM_THRDS];&lt;br /&gt;        IAsyncResult ars[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; IAsyncResult[NUM_THRDS];&lt;br /&gt;        WaitHandle _handles[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; WaitHandle[NUM_THRDS];&lt;br /&gt;     &lt;br /&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i=0; i&amp;lt;NUM_THRDS; i++) {&lt;br /&gt;            tasks[i] = &lt;span class="kwrd"&gt;new&lt;/span&gt; taskDelegate(task);&lt;br /&gt;            ars[i] = tasks[i].BeginInvoke(&lt;span class="str"&gt;"Thread #"&lt;/span&gt; + i,&lt;br /&gt;                &lt;span class="kwrd"&gt;new&lt;/span&gt; AsyncCallback(aCallback), &lt;br /&gt;                tasks[i]&lt;br /&gt;            );&lt;br /&gt;            _handles[i] = ars[i].get_AsyncWaitHandle();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// use wait handles to ensure threads complete before continuing&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// in this example we are just printing data,&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;//    but this is useful if after async calls you need to sort/manipulate results.&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; NUM_THRDS; i++)&lt;br /&gt;        {&lt;br /&gt;            _handles[i].WaitOne();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            Thread.sleep(5000L);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (InterruptedException e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;// exception handling&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        tasks = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        ars = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;/* Asynchronous callback method used to call EndInvoke and process results */&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; aCallback(IAsyncResult ar) {&lt;br /&gt;        taskDelegate t = (taskDelegate)ar.get_AsyncState();&lt;br /&gt;        AsyncResult aResult = (AsyncResult)ar;&lt;br /&gt;        taskDelegate temp = (taskDelegate)(aResult.get_AsyncDelegate());&lt;br /&gt;        System.&lt;span class="kwrd"&gt;out&lt;/span&gt;.println(temp.EndInvoke(ar));&lt;br /&gt;        t = &lt;span class="kwrd"&gt;null&lt;/span&gt;; temp = &lt;span class="kwrd"&gt;null&lt;/span&gt;; aResult = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; String task(String x)&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;try&lt;/span&gt; {&lt;br /&gt;            Thread.sleep(2000L);&lt;br /&gt;        } &lt;span class="kwrd"&gt;catch&lt;/span&gt;(InterruptedException e) {&lt;br /&gt;            &lt;span class="rem"&gt;// exception handling&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; (x.trim() + &lt;span class="str"&gt;": "&lt;/span&gt; + System.DateTime.get_Now().ToString());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I tried to correlate other examples/practices in here like the use of a static initializer to set the size of the pool or other data/objects you want done once, but the remainder of the code is straight from documentation on the different .NET classes as mentioned above. Note the use of the AsyncWaitHandles, as I have found it is a good way to signal the calling thread when all the Async activities have completed.  Otherwise, you can start a loop from the number of total threads and do i-- (decrement counter) within AsyncCallback method to indicate the number of threads still running.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-4342156870753328351?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/4342156870753328351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=4342156870753328351' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/4342156870753328351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/4342156870753328351'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/concurrent-threading-series-j-revisited.html' title='Concurrent Threading Series (J# Revisited)'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-392212032080397831</id><published>2007-09-06T19:53:00.000-04:00</published><updated>2007-09-06T20:56:48.847-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Bringing The Background To The Foreground</title><content type='html'>One point to make on multi-threading applications if I have not done a good job of making it clear is that it should be done with a good deal of responsibility with regarding to synchronization or protection against threads colliding with each other, exception handling, and resource management.&lt;br /&gt;&lt;br /&gt;With the discussion on using thread pool or normal threads mentioned at the end of my last post, I realized I used the term "background" threads a good deal, but did not show how to implement one or what the difference was between a thread running in the background according to my definition and a background thread as implemented in programming language.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language run-time ends the process. Any remaining background threads are stopped and do not complete. &lt;span align="right"&gt;-&lt;a href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx"&gt;MSDN&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Threads that belong to the managed thread pool (that is, threads whose IsThreadPoolThread property is true) are background threads. All threads that enter the managed execution environment from unmanaged code are marked as background threads. All threads generated by creating and starting a new Thread object are by default foreground threads. &lt;span align="right"&gt;-&lt;a href="http://msdn2.microsoft.com/en-us/library/h339syd0.aspx"&gt;MSDN&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;If you follow the first link above, the MSDN library entry has the following code for illustrating the difference in how the background and foreground threads are treated at termination of application.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System&lt;br /&gt;&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System.Threading&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; Test&lt;br /&gt;&lt;br /&gt;    &amp;lt;MTAThread&amp;gt; _&lt;br /&gt;    &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Main()&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; shortTest &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; BackgroundTest(10)&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; foregroundThread &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Thread(&lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; shortTest.RunLoop)&lt;br /&gt;        foregroundThread.Name = &lt;span class="str"&gt;"ForegroundThread"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; longTest &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; BackgroundTest(50)&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; backgroundThread &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Thread(&lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; longTest.RunLoop)&lt;br /&gt;        backgroundThread.Name = &lt;span class="str"&gt;"BackgroundThread"&lt;/span&gt;&lt;br /&gt;        backgroundThread.IsBackground = &lt;span class="kwrd"&gt;True&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        foregroundThread.Start()&lt;br /&gt;        backgroundThread.Start()&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; BackgroundTest&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; maxIterations &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Sub&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt;(maximumIterations &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;)&lt;br /&gt;        maxIterations = maximumIterations&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Sub&lt;/span&gt; RunLoop()&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; threadName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = Thread.CurrentThread.Name&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; maxIterations&lt;br /&gt;            Console.WriteLine(&lt;span class="str"&gt;"{0} count: {1}"&lt;/span&gt;, _&lt;br /&gt;                    threadName, i.ToString())&lt;br /&gt;            Thread.Sleep(250)&lt;br /&gt;        &lt;span class="kwrd"&gt;Next&lt;/span&gt; i&lt;br /&gt;&lt;br /&gt;        Console.WriteLine(&lt;span class="str"&gt;"{0} finished counting."&lt;/span&gt;, threadName)&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; Class&lt;/pre&gt;&lt;br /&gt;As stated previously, I have found "background" threads really useful for statistical analysis/logging activities that are not necessary for functionality of user request, but need data from request to get started. So the user doesn't wait for long time for a response, the application calculates results for user while spawning a background thread for performing business logic, file I/O, database calls, etc. necessary.&lt;br /&gt;&lt;br /&gt;This works well keeping in mind whether or not it is important to you to maintain any statistical threads still running at application shutdown. With .NET typically being hosted on a Microsoft IIS server where application pools cycle periodically, the need to use foreground thread or programmatic handling of background threads on application end (global.asax) may be more prevalent.&lt;br /&gt;&lt;br /&gt;I will try to be careful on how I use the term "background" as I tend to use this to refer to any thread that does not need to run while a user is waiting/watching.&lt;br /&gt;&lt;br /&gt;Anyway, just a little tidbit of information to add to the arsenal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-392212032080397831?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/392212032080397831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=392212032080397831' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/392212032080397831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/392212032080397831'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/bringing-background-to-foreground.html' title='Bringing The Background To The Foreground'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-6217957504694445524</id><published>2007-09-06T19:11:00.000-04:00</published><updated>2007-09-06T19:21:52.475-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cool tools'/><title type='text'>Code Formatter for Blogs/Web Pages</title><content type='html'>Since I have been copying and pasting in code recently pretty frequently and trying to format, I thought I should post a really cool web tool I found that is great for formatting code snippets for placement in blog posts or HTML in general. If you have not seen the new look on my previous posts that I have retrofitted using this tool, take a look and see.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.manoli.net/csharpformat/"&gt;http://www.manoli.net/csharpformat/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You will find the tool is good for VB and C#. Since Java is very close in color coding scheme to C#, I used the tool with C# selection and worked out decently.&lt;br /&gt;&lt;br /&gt;The formatting uses CSS, so you will have to copy the following CSS code into the template page of your blog or update the linked CSS file from the site with this code and reference as indicated.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;    font-size: small;&lt;br /&gt;    color: black;&lt;br /&gt;    font-family: Consolas, &lt;span class="str"&gt;"Courier New"&lt;/span&gt;, Courier, Monospace;&lt;br /&gt;    background-color: #f4f4f4;&lt;br /&gt;    white-space: pre-wrap;       &lt;span class="rem"&gt;/* css-3 */&lt;/span&gt;&lt;br /&gt;    white-space: -moz-pre-wrap;  &lt;span class="rem"&gt;/* Mozilla, since 1999 */&lt;/span&gt;&lt;br /&gt;    white-space: -pre-wrap;      &lt;span class="rem"&gt;/* Opera 4-6 */&lt;/span&gt;&lt;br /&gt;    white-space: -o-pre-wrap;    &lt;span class="rem"&gt;/* Opera 7 */&lt;/span&gt;&lt;br /&gt;    word-wrap: &lt;span class="kwrd"&gt;break&lt;/span&gt;-word;       &lt;span class="rem"&gt;/* Internet Explorer 5.5+ */&lt;/span&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;    background-color: #f4f4f4;&lt;br /&gt;    width: 100%;&lt;br /&gt;    margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Update adds text wrap for browsers that don't automatically do so with use of the pre HTML element.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-6217957504694445524?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/6217957504694445524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=6217957504694445524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/6217957504694445524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/6217957504694445524'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/code-formatter-for-blogsweb-pages.html' title='Code Formatter for Blogs/Web Pages'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-5416794607047549925</id><published>2007-09-06T17:42:00.001-04:00</published><updated>2007-09-06T20:52:05.798-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Calling All Threads Again (Async Revisited)</title><content type='html'>&lt;a href="http://crossedlogic.blogspot.com/2007/08/multi-threading-background-processes-is.html"&gt;overview&lt;/a&gt;, &lt;a href="http://crossedlogic.blogspot.com/2007/09/calling-all-threads.html"&gt;calling all threads&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So in the last post, we &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;illustrated&lt;/span&gt; how to recreate Java code for &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;parallel&lt;/span&gt; processing in Visual Basic .NET. One of the design features used in the implementation of retrieving data from task submitted to thread pool work item queue was to use a wait object to ensure that the thread completed before trying to collect the results.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Well that is the point of asynchronous processing, right: invoke a thread and then continue to do other work in main thread until work is complete. In our case, the additional processing we want to do is to start more threads or at least submit them to the queue and then we are satisfied in waiting for the results. Here is a look at the .NET asynchronous programming &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;methodology&lt;/span&gt; for accomplishing what was done in my implementation of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;ATask&lt;/span&gt; by creating my &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;BeginTask&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;EndTask&lt;/span&gt; routines. This should look very similar as asynchronous methods within .NET employ the same logic of beginning/invoking action with one method then ending/responding through another. The difference is that .NET will create all these methods for us versus my manually coded ones in previous post.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;...&lt;br /&gt;    &lt;span class="kwrd"&gt;Delegate&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;TaskDelegate&lt;/span&gt;(&lt;span class="kwrd"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;ByVal&lt;/span&gt;&lt;/span&gt; x &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Main()&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;str&lt;/span&gt; &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = &lt;span class="str"&gt;"test"&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; t &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;TaskDelegate&lt;/span&gt; = &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;TaskDelegate&lt;/span&gt;(&lt;span class="kwrd"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;AddressOf&lt;/span&gt;&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;ATask&lt;/span&gt;)&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;ar&lt;/span&gt; &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;IAsyncResult&lt;/span&gt; = t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;BeginInvoke&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;str&lt;/span&gt;, &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;, &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;)&lt;br /&gt;        Console.WriteLine(t.EndInvoke(ar))&lt;br /&gt;        &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;ar&lt;/span&gt; = t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;BeginInvoke&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;str&lt;/span&gt; + &lt;span class="str"&gt;" second run!"&lt;/span&gt;, &lt;span class="kwrd"&gt;New&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;AsyncCallback&lt;/span&gt;(&lt;span class="kwrd"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;AddressOf&lt;/span&gt;&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;ACallback&lt;/span&gt;), t)&lt;br /&gt;        System.Threading.Thread.Sleep(5000L)&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Function&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;ATask&lt;/span&gt;(&lt;span class="kwrd"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;ByVal&lt;/span&gt;&lt;/span&gt; x &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;Return&lt;/span&gt; x.Trim()&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Sub&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;ACallback&lt;/span&gt;(&lt;span class="kwrd"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;ByVal&lt;/span&gt;&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;ar&lt;/span&gt; &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;IAsyncResult&lt;/span&gt;)&lt;br /&gt;        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; t &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;TaskDelegate&lt;/span&gt; = &lt;span class="kwrd"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;DirectCast&lt;/span&gt;&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;ar&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;AsyncState&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;TaskDelegate&lt;/span&gt;)&lt;br /&gt;        Console.WriteLine(t.EndInvoke(ar))&lt;br /&gt;    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;The first piece of this code starts with the creation of worker function/class like the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;ATask&lt;/span&gt;.Task method from my last post. Above, this is represented by my highly complicated method &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;ATask&lt;/span&gt;(String). Secondly, a delegate is declared with the same signature as function/sub routine created to do work.&lt;br /&gt;&lt;br /&gt;As stated earlier, .NET will take care of creating the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;BeginInvoke&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;EndInvoke&lt;/span&gt; methods appropriately. Subsequently, the first call to t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;BeginInvoke&lt;/span&gt; starts the processing of our task with the specified parameter data contained in the variable &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;str&lt;/span&gt;. The t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;EndInvoke&lt;/span&gt; returns a String as we instructed through the signature of method, so in our simple example, the result is fed right to console.&lt;br /&gt;&lt;br /&gt;For more of a "Fire and Forget" implementation, the remaining parameters, we initially ignored in t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;BeginInvoke&lt;/span&gt; by passing "Nothing" or null, are used. The first of the two is used to specify a callback method that has signature like &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;ACallback&lt;/span&gt;. This method handles calling the t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;EndInvoke&lt;/span&gt;. The second omitted parameter is used to pass the invocation the delegate object itself. As you will see in the second call to t.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;BeginInvoke&lt;/span&gt;, we are able to start the processing of work and then the results will be collected when ready by the callback method.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Where's The Pool&lt;br /&gt;&lt;/strong&gt;If you have been following along and aren't experts at this, you may be wondering what happening to the thread pool as we have been promoting the use of pooling since our worker thread count can go from one to 10,000. The fixed thread pool is great for ensuring that our system/application stays stable, so why eliminate it. Well, from what I have gathered, asynchronous threads are always run in the shared thread pool provided by the Common Language &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;Runtime&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;CLR&lt;/span&gt;). Therefore, my understanding is that we do not need to submit these tasks to user work item queue.&lt;br /&gt;&lt;br /&gt;With all this swimming around in a shared thread pool, there is a potential that managed code or other long running processes may be utilizing threads needed by this specific application or vice &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;versa&lt;/span&gt;, so one thought is to use custom thread pooling. Custom thread pool development is not covered in this post, but I have found many different references to a &lt;a onclick="return top.js.OpenExtLink(window,event,this)" href="http://www.bearcanyon.com/dotnet/threadpool.zip" target="_blank"&gt;fully implemented C# code from Mike &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;Woodring&lt;/span&gt;&lt;/a&gt;. This would allow for processes using shared thread pool that we can't control to have adequate resources while ensuring that our application does not create an &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_49"&gt;exorbitant&lt;/span&gt; amount of threads.&lt;br /&gt;&lt;br /&gt;One interesting thought I had on this was to see if using standard threads if I could effectively code a mechanism in which I launch a finite number of threads (e.g. 15) and then monitor for the completion of any of the threads so that another iteration of the task can be spawned in that thread until all the tasks are complete. This is the concept behind thread pool, but just wondering if it can be done without the entire code associated with a full blown thread pool. This intrigues me as I can think of applications where it may be useful to spawn a set of processes within a thread pool and then to make them run faster spawn numerous non-pooled background threads. This eliminates some possibilities of deadlocks or issues with using shard pool, as our threads would not need to stay in the pool long as they would return rapidly. The pool would just be used for queueing the iteration of main working process while the background threads would be working on finite tasks within a working process instance.&lt;br /&gt;&lt;br /&gt;Why not do this all with background threads if we can control their execution to be efficient?&lt;br /&gt;&lt;br /&gt;We will see how my crazy mind develops this thought. May be easier just to grab the custom thread pool from Mike &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;Woodring's&lt;/span&gt; site and make a reference to a compiled &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;DLL&lt;/span&gt; that already has this work done. Why re-invent the wheel, right? Probably why I found other sites that had reference to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;DevelopMentor&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;ThreadPool&lt;/span&gt; as they just decided to copy his too.&lt;br /&gt;&lt;br /&gt;The adventure continues...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-5416794607047549925?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/5416794607047549925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=5416794607047549925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/5416794607047549925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/5416794607047549925'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/calling-all-threads-again-async.html' title='Calling All Threads Again (Async Revisited)'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-5792852816056343668</id><published>2007-09-05T00:24:00.000-04:00</published><updated>2008-01-28T22:12:08.658-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Calling All Threads</title><content type='html'>&lt;a href="http://crossedlogic.abdu-shahid.com/downloads/aot.vb.src.zip"&gt;example source code&lt;/a&gt;, &lt;a href="http://crossedlogic.blogspot.com/2007/08/multi-threading-background-processes-is.html"&gt;overview&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is always room for improvement, so I won't say we are at journey's end; however, this is at least in the right vicinity. The original intent of this series was to show concurrent programming in .NET as it was done in a real life Java application. There are components of this transition that are fairly straightforward as some objects conceptually map directly to that of original implementation, despite syntactical differences. My hope is that the information presented below will be useful in bringing the business and programming concepts together as well as point out places where the implementation is not as obvious.&lt;br /&gt;&lt;br /&gt;Firstly, let's begin with the creation of the "thread" class. Microsoft .NET does not allow the inheritance of the Thread class or have Runnable or Callable interfaces to implement. Instead, using an additional class or member function within the main object, threads are created through use of a delegate function. Threads are instanced by calling the constructor of System.Threading.Thread, passing it a reference to the delegate function.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; Thread1 &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Threading.Thread(&lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; delegateFunction)&lt;br /&gt;Thread1.Start()&lt;/pre&gt;&lt;br /&gt;However, as we discussed in previous posts, we want to use pooled threads versus multiple threads called in succession. With that said, the format to spawn a thread in .NET into a pool requires the submission of a WaitCallback delegate, which has a signature of delegateFunction(Arg As Object), to the shared System.Threading.ThreadPool object that can be likened (hopefully without ridicule) to the fixed thread pool ExecutorService we utilized in Java. The object argument passed to the delegate function holds both the input parameters and variable(s) for output after thread processing has completed. See the AStateObject class in the linked source files as an example.&lt;br /&gt;&lt;br /&gt;The general setup of a delegate function and use of thread pooling is shown below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;...&lt;br /&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; BeginTask(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; thrdNum &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; isVarCalcTime &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;)&lt;br /&gt;   state = &lt;span class="kwrd"&gt;New&lt;/span&gt; AStateObject(thrdNum, isVarCalcTime)&lt;br /&gt;   &lt;span class="rem"&gt;'ThreadPool is a shared/static system object&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;'that can be likened to the Java ExecutorService object&lt;/span&gt;&lt;br /&gt;   ThreadPool.QueueUserWorkItem(&lt;span class="kwrd"&gt;New&lt;/span&gt; WaitCallback(&lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; Task), state)&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Function&lt;/span&gt; EndTask() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;&lt;br /&gt;   semaphore.WaitOne()&lt;br /&gt;   &lt;span class="kwrd"&gt;Return&lt;/span&gt; state.Status&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Sub&lt;/span&gt; Task(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; StateObj &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;)&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; varCalcTime &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Long&lt;/span&gt; = AStateObject.DEFAULT_VAR_CALC_TIME&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; thrdnum &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = AStateObject.DEFAULT_THRD_NUM&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; isVarCalcTime &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt; = AStateObject.DEFAULT_IS_VAR_CALC_TIME&lt;br /&gt;   &lt;span class="rem"&gt;' Use the state object fields as arguments.&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; StObj &lt;span class="kwrd"&gt;As&lt;/span&gt; AStateObject = &lt;span class="kwrd"&gt;CType&lt;/span&gt;(StateObj, AStateObject)&lt;br /&gt;   isVarCalcTime = StObj.IsVarCalcTime&lt;br /&gt;   thrdnum = StObj.ThrdNum&lt;br /&gt;   &lt;span class="kwrd"&gt;If&lt;/span&gt; isVarCalcTime &lt;span class="kwrd"&gt;Then&lt;/span&gt; varCalcTime = AStateObject.getRandomCalcTime()&lt;br /&gt;&lt;br /&gt;   &lt;span class="rem"&gt;'Can use SyncLock or other synchronization techniques&lt;/span&gt;&lt;br /&gt;   &lt;span class="rem"&gt;'for real life calc that may hit backend systems&lt;/span&gt;&lt;br /&gt;   &lt;span class="rem"&gt;'Data that may be touched by multiple tasks simultaneously&lt;/span&gt;&lt;br /&gt;   Thread.Sleep(2000L + varCalcTime)&lt;br /&gt;   &lt;span class="rem"&gt;'SyncLock StObj&lt;/span&gt;&lt;br /&gt;   StObj.Status = &lt;span class="kwrd"&gt;Date&lt;/span&gt;.Now() &lt;span class="rem"&gt;'Return value&lt;/span&gt;&lt;br /&gt;   &lt;span class="rem"&gt;'End SyncLock&lt;/span&gt;&lt;br /&gt;   semaphore.&lt;span class="kwrd"&gt;Set&lt;/span&gt;()   &lt;span class="rem"&gt;' Signal that the thread is done.&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The Task subroutine is the delegate that does the processing we want. This can be coded to perform business logic directly or call a web service or other API that does the processing/calculations for us. The object passed to the delegate is really done by reference despite the method signature as what is passed by value is the address of the object itself; therefore, interactions with this object like setting Status which is the return data object set values in the original instance of AStateObject in our case. The thread pool is then passed a user work item through WaitCallback delegate and the AStateObject associated.&lt;br /&gt;&lt;br /&gt;As with the Java implementation, it is most efficient to submit all the threads to the pool for processing then circle back and retrieve results once each thread is ready to yield it. If we wait for thread to finish to get result at same time we add to user work item queue, then we may as well submit threads sequentially or allow the main process to iterate task without overhead of creating more threads. Assuming we want the efficiency, what you will see in the class ATask is that the invocation/queuing of task is done in a BeginTask and then the response is queried through calling EndTask.&lt;br /&gt;&lt;br /&gt;The calls from the main process occur in this phased fashion as well, very similar to how it was implemented in Java as we also used three sections there: create threads; read results/wait; display results.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;...&lt;br /&gt;    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; NUM_THRDS &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 100, I &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tasks(NUM_THRDS) &lt;span class="kwrd"&gt;As&lt;/span&gt; ATask&lt;br /&gt;    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; status(NUM_THRDS) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;'Start threads&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;For&lt;/span&gt; I = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; (NUM_THRDS - 1)&lt;br /&gt;        tasks(I) = &lt;span class="kwrd"&gt;New&lt;/span&gt; ATask()&lt;br /&gt;        tasks(I).BeginTask(I, &lt;span class="kwrd"&gt;True&lt;/span&gt;)&lt;br /&gt;    &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;'Get the result of the threads&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;For&lt;/span&gt; I = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; (NUM_THRDS - 1)&lt;br /&gt;        &lt;span class="kwrd"&gt;Try&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;'Not using any processing that will throw an error,&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;'but just wanted to show as an example&lt;/span&gt;&lt;br /&gt;            status(I) = tasks(I).EndTask()&lt;br /&gt;        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception&lt;br /&gt;            status(I) = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;For&lt;/span&gt; I = (NUM_THRDS - 1) &lt;span class="kwrd"&gt;To&lt;/span&gt; 0 &lt;span class="kwrd"&gt;Step&lt;/span&gt; -1&lt;br /&gt;        &lt;span class="kwrd"&gt;If&lt;/span&gt; status(I) = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt; status(I) = &lt;span class="str"&gt;"Empty"&lt;/span&gt;&lt;br /&gt;        Console.WriteLine(&lt;span class="str"&gt;"Thread #"&lt;/span&gt; + I.ToString + &lt;span class="str"&gt;": "&lt;/span&gt; + status(I).ToString())&lt;br /&gt;    &lt;span class="kwrd"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;'Clean-up objects used&lt;/span&gt;&lt;br /&gt;    status = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;&lt;br /&gt;    tasks = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The significance to this approach is that after the process has been put into a thread pool, the results cannot be extracted until after the process has fully completed. Therefore, the EndTask function waits on the thread making the middle block of code very much sequential, but since the threads run concurrently before hand it adds minimal if any processing overhead as you should never wait any longer than the longest running thread in the bunch. Since "run time" in the context of longest running process includes the amount of time a thread must sit in the queue, now may be a good time to show the syntax for increasing the thread pool size.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;ThreadPool.SetMaxThreads(workerThreads, completionPortThreads)&lt;/pre&gt;&lt;br /&gt;Both parameters are integers representing the quantity of each type of thread available in the pool. Since .NET employs a shared thread pool, this follows the principal of finding the right number of threads for all concurrent users of the application. As the application is idle, users will have a faster response, then will slow down as load grows to ensure stability of system as too many threads can be as lethal as not enough.&lt;br /&gt;&lt;br /&gt;Putting it all together, we have an application that emulates our Java example and yields pretty equal results (see &lt;a href="http://crossedlogic.abdu-shahid.com/vb/aot/threadpoolingexample_out.txt"&gt;example output&lt;/a&gt;). Hopefully this was successful in meeting my intent, which was to place links and thoughts around multi-threading in .NET (for Java developers) especially around concurrency. In trying to stick closely to the layout/concepts in the Java implementation, I am sure I have put together some odd .NET constructs, so all you VB/.NET purists out there must forgive me.&lt;br /&gt;&lt;br /&gt;10,000 threads are still better than one if used tactically, especially as we move to a world of even faster response times with asynchronous interfaces. A follow-up to this exercise may be to show how to improve the user interface portion of the application to display some of the results immediately to browser/screen like how many items are in stock today as the program processes the results for items that need to be built for example in our item availability service. We'll see if I can wrap my brain around using the IAsyncResult process in-line with the other concepts here, but, until then...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;keep evolving development&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-5792852816056343668?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/5792852816056343668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=5792852816056343668' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/5792852816056343668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/5792852816056343668'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/calling-all-threads.html' title='Calling All Threads'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-3391580572386773809</id><published>2007-09-01T18:46:00.000-04:00</published><updated>2007-09-04T08:26:46.688-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j#'/><title type='text'>Migrating to J# From Java</title><content type='html'>&lt;a href="http://crossedlogic.blogspot.com/2007/08/multi-threading-background-processes-is.html"&gt;overview&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="color:#000099;"&gt;Microsoft's J# is like Cappuccino, it is pretty much Java with some extra frosting on top.&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;Microsoft's J#, syntactically, is very much the same as Java; therefore, when this adventure to migrate the availability code to .NET presented itself, my first thought was "convert to J#." Unfortunately, with the features we explored previously being functionality of JDK level 5.0, J# could not actual accomplish this task.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;According to Microsoft, J#'s run-time libraries will remain frozen at the JDK 1.1.4 level; there are no plans to emulate later versions of the JDK. If J# catches on, it's likely that users will fill in the gaps over time. Microsoft considers JDK compatibility largely irrelevant. The current level supports Visual J++ projects, and whatever is missing from the JDK compatibility libraries is covered by the .Net framework. &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;J#'s interface to the .Net framework is solid, but not as seamless as C#. In particular, J# code cannot define new .Net properties, events, value types, or delegates. J# can make use of these language constructs if they are defined in an assembly written in another language, but its inability to define new ones limits J#'s reach and interoperability compared to other .Net languages.&lt;/p&gt;&lt;p align="right"&gt;-Tom Yager, &lt;a href="http://www.infoworld.com/articles/tc/xml/01/11/05/011105tcjsharp.html"&gt;Infoworld&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Presumably due to legality issues restricting Microsoft from copying Java bytecode for bytecode, coupled with strategic desire to push developers towards using core .NET functionality to accomplish the tasks done in later Java versions, the J# support for newer JDKs will probably not be updated to cover the holes in it current capabilities.&lt;/p&gt;&lt;p&gt;With that said, for my case study, I have come to the realization that code must be re-written in .NET and it will be in Visual Basic. C# is probably the more powerful than Visual Basic .NET; however, the target business system being written in Visual Basic makes it the more desirable for this project. &lt;/p&gt;&lt;p&gt;Don't get me wrong, though, there is a good deal of power in being able to compile java directly into .NET using J#, but just be aware of the limitations. It took me a while to stop seeing 1.1.4 and thinking 1.4, so for the application I was converting there was too much of a gap.&lt;/p&gt;&lt;p&gt;For you developers who have Java applications that would be hard to re-write, J# .NET may fit the need, especially when using tools such as &lt;a href="http://www.ikvm.net/"&gt;IKVM&lt;/a&gt; or &lt;a href="http://msdn2.microsoft.com/en-us/library/sxh73yst(VS.80).aspx"&gt;JBImp&lt;/a&gt; that allow conversion of Java bytecode to Microsoft intermediate language (MSIL). However, this may also be a good argument for using C#, which syntactically is close to that of Java as C/C++ is. After converting Java classes or archive (JAR) files to .NET libraries, migration of application to C# becomes easier.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-3391580572386773809?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/3391580572386773809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=3391580572386773809' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3391580572386773809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3391580572386773809'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/09/migrating-j-from-java.html' title='Migrating to J# From Java'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-3523306931181472561</id><published>2007-08-30T20:41:00.000-04:00</published><updated>2008-01-28T22:11:14.732-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Jump In The Pool, The Threads Are Fine</title><content type='html'>&lt;a href="http://crossedlogic.abdu-shahid.com/downloads/aot.java.src.zip"&gt;example source code&lt;/a&gt;, &lt;a href="http://crossedlogic.blogspot.com/2007/08/multi-threading-background-processes-is.html"&gt;overview&lt;/a&gt;, &lt;a href="http://crossedlogic.blogspot.com/2007/08/10000-threads-are-better-than-one.html"&gt;java part I&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;blockquote style="COLOR: rgb(0,0,153)"&gt;10,000 soldiers may be more powerful than one, but, if they march in a straight line towards enemy fire, they are no more effective.&lt;/blockquote&gt;&lt;br /&gt;Threads are the same. Marching them in regiments versus a line adds power and efficiency at the same time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Thread Pooling&lt;/span&gt;&lt;br /&gt;In &lt;a href="http://www.java.com/"&gt;Java 5.0&lt;/a&gt; (JRE 1.5), the &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/package-summary.html"&gt;java.util.concurrent&lt;/a&gt; package was made available which provided API for concurrent processing/efficient thread pooling. For some good details on the API, please refer to Java/Sun publications on JSR 166. The Distributed Computing Laboratory at Emory University has further documentation as well as a &lt;a href="http://dcl.mathcs.emory.edu/util/backport-util-concurrent/"&gt;back-ported version of the package&lt;/a&gt; for use with older versions of JVM.&lt;br /&gt;&lt;br /&gt;To implement the concurrent/thread pool model to the ArrayOfThreads object we created in previous post, the ExecutorService is utilized to invoke a Callable object (introduced in the concurrent package). AThread happens to be a Callable object versus a simple sub-class of Thread object which just has a run() method without a return. Utilized the Callable even in the earlier examples as the end goal is to be able to gather data back from the execution of this process.&lt;br /&gt;&lt;br /&gt;Consequently, after submission of threads for processing, the framework for concurrency provides a mechanism to retrieve returned data per thread using the Future object. The major difference this makes in the implementation is that the Future handles the waiting and gathering of thread data, so the main application thread spawning the new processes does not have to wait until each thread completes before moving on.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/* code snippet from ArrayOfThreadsPooled.java&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;* @see java.util.concurrent.Executors&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;* @see java.util.concurrent.ExecutorService&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;* @see java.util.concurrent.Future&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; NUM_THRDS = 100, NUM_THRDS_POOLED = 100;&lt;br /&gt;ExecutorService tpes = Executors.newFixedThreadPool(NUM_THRDS_POOLED);&lt;br /&gt;Future futures[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; Future[NUM_THRDS];&lt;br /&gt;AThread calculators[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; AThread[NUM_THRDS];&lt;br /&gt;Object status[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; Object[NUM_THRDS];&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Later on using a for loop to instantiate the threads, we submit each to pool (where i represents the integer index used in loop).&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;calculators[i] = &lt;span class="kwrd"&gt;new&lt;/span&gt; AThread(i);&lt;br /&gt;futures[i] = tpes.submit(calculators[i]);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On the first implementation of ArrayOfThreadsPooled we see that the process impracticality of running multiple threads has been removed as the process time is about a hundredth of the time since all 100 threads execute simultaneously (see &lt;a href="http://crossedlogic.abdu-shahid.com/java/aot/arrayofthreadspooled_out.txt"&gt;output example 1&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Don't Be A Resource Hog&lt;/span&gt;&lt;br /&gt;However, the problem of scaling is still an issue as your business systems involved in processing and application server itself will probably not appreciate the execution of 10,000 threads. To remedy this per user, the ArrayOfThreadsPooledv2 is enhanced by illustrating the fact that the fixed thread pool does not need to have the same size as the required amount of Callables, Futures, et al. Therefore, the NUM_THRDS_POOLED value can be changed to a lower or higher number than 100.&lt;br /&gt;&lt;br /&gt;For example I found that my application worked with a total number of 15 processors running at a time (see &lt;a href="http://crossedlogic.abdu-shahid.com/java/aot/arrayofthreadspooledv2_out1.txt"&gt;output example 2&lt;/a&gt;). To better understand the benefit, the AThread class provided includes the ability to provide variable processing times. With variance in execution times, the thread pool with stop and start threads appropriately thus adding even more efficiencies over executing x number of threads at a time with identical run times (see &lt;a href="http://crossedlogic.abdu-shahid.com/java/aot/arrayofthreadspooledv2_out2.txt"&gt;output example 3&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;Back 2 The Future&lt;/span&gt;&lt;br /&gt;Through the Future get() method wrapped with exception handling, we can retrieve the returned object/data from the Callable later on.&lt;br /&gt;&lt;br /&gt;Since the Futures involved take care of getting data, as a developer you get the benefit of all the threads starting at once, but having a method of identifying which response goes to which request. With this information, you can then sort, analyze, manipulate or otherwise report the data however you see fit.&lt;br /&gt;&lt;br /&gt;Some further enhancements to this would be o find the optimum amount of threads needed to support all requests from your client base and instantiate the ExecutorService as one static version defined globally for the application.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public static int&lt;/span&gt; NUM_THRDS_CONCURRENT = 60;&lt;br /&gt;&lt;span class="kwrd"&gt;public static&lt;/span&gt; ExecutorService tpes =&lt;br /&gt;Executors.newFixedThreadPool(NUM_THRDS_CONCURRENT);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Each instance of ArrayOfThreadsPooledv2 that were executed would, therefore, submit its number of Callable objects necessary into the shared pool.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;futures[i] = ArrayOfThreadsPooledv2.tpes.submit(calculators[i]);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If no other users were on, the response may be as quick as first iteration of ArrayOfThreadsPooled while providing the stability and respect of resources provided by second implementation.&lt;br /&gt;&lt;br /&gt;With the source code and detail to this point, I hope those of you on the journey towards creating a multi-threaded application in Java have found enough useful information to utilize the full power of Java's great addition. Keep in mind that further enhancements exist in JRE 1.6.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Keep evolving development!&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-3523306931181472561?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/3523306931181472561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=3523306931181472561' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3523306931181472561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3523306931181472561'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/08/jump-in-pool-threads-are-fine.html' title='Jump In The Pool, The Threads Are Fine'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-43777090475124743</id><published>2007-08-30T17:14:00.000-04:00</published><updated>2008-01-28T22:06:08.560-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>10,000 Threads Are Better Than One</title><content type='html'>&lt;a href="http://crossedlogic.abdu-shahid.com/downloads/aot.java.src.zip"&gt;example source code&lt;/a&gt;, &lt;a href="http://crossedlogic.blogspot.com/2007/08/multi-threading-background-processes-is.html"&gt;overview&lt;/a&gt; &lt;div&gt;In this post we will be following the business logic for using multi-threading and concurrency as we explore the expansion of the availability service from its basic form to one extended for more practical application presented in the previous posting.&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="COLOR: rgb(0,0,153)"&gt;[basic availability service] an application that communicated with business systems (enterprise resource planning - inventory management in particular) to read current stock information, including current demand allocations; compare to new single demand; ultimately, displaying lead time to fulfill customer requirement whether from stock, assembling from stocked components on a bill of material, or purchasing/fabricating item through the portions if not all of its cumulative lead time...&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Since the business world does not exist in a parallel universe where customer demand and actual supply are always in constant harmony, the basic implementation for availability above is insufficient as a final answer to a demand requirement that has differing priorities (e.i. fulfill two or more needs at once). To clarify, please re-read the following excerpt:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="COLOR: rgb(0,0,153)"&gt;[extended availability service] As a customer, you may have an immediate need for five light bulbs or else you will be in darkness for the entire day, but you get cost efficiencies purchasing light bulbs in quantities of 1,000. The purpose of this extension to the availability service is to allow you as the customer understand that you can get 50 from stock today...&lt;/blockquote&gt;&lt;br /&gt;The first need of concern is to restore service: get the lights on! The second priority is to ensure that the effort to restore service is done in a fashion that positively impacts the bottom-line long term as well as lessen the likelihood of future outage. At its most basic sense, the response to the above variation in need could involve two calls to availability code: one returning lead time of quantity acquirable through stock (e.g. same day); the other, time through procurement/manufacturing processes (e.g. 60 days).&lt;br /&gt;&lt;br /&gt;However, if you add usage and more complex items an scenarios to your thought process over my simple light bulb shortage, the application requirement slowly becomes (or at least it did in my case) one that asks the question "what is the individual lead time of each quantity of the total 1,000 light bulbs requested?"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="FONT-WEIGHT: bold"&gt;An Array of Threads&lt;/span&gt;&lt;br /&gt;Following the thought above, to answer the question, a user of the availability tool would run sequential requests with required quantities from 1 - 1,000. The first step is to change the process of making the requests an automated one versus having to make 1,000 separate requests. The user would like to query the system once and get 1,000 responses. With the potential for thousands or tens of thousands, the first logical conclusion I got was "10,000 threads are better than one."&lt;br /&gt;&lt;br /&gt;The example thread AThread does a simple wait(x milliseconds) to simulate some processing time, but can easily be modified to be a synchronized (depending on locking requirements) block of code executing logic necessary to determine a specific item and required quantity availability. For example:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/* call() method for AThread.java&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;* @see java.util.concurrent.Callable#call()&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; Object call() throws Exception {&lt;br /&gt;&lt;span class="rem"&gt;// Define your own result object and availability processor&lt;/span&gt;&lt;br /&gt;LeadTimeResultObject ltro = &lt;span class="kwrd"&gt;new&lt;/span&gt; LeadTimeResultObject();&lt;br /&gt;AvailabilityProcessor process = &lt;span class="kwrd"&gt;new&lt;/span&gt; AvailabilityProcessor();&lt;br /&gt;&lt;span class="rem"&gt;// Use synchronized blocks for thread safety&lt;/span&gt;&lt;br /&gt;synchronized(&lt;span class="kwrd"&gt;this&lt;/span&gt;){&lt;br /&gt;   &lt;span class="rem"&gt;// Insert application logic to get lead time&lt;/span&gt;&lt;br /&gt;ltro = process.getLeadTimeResult(&lt;span class="str"&gt;"some item id"&lt;/span&gt;, &lt;span class="str"&gt;"some quantity"&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; ltro;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;The ArrayOfThreads class illustrates how to implement calling the lead time availability code through use of an AThread array.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;AThread calculators[] = &lt;span class="kwrd"&gt;new&lt;/span&gt; AThread[100];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Using a for loop to iterate from 0 to 99 index of array, you can use the Constructor of the AThread object to pass in data needed to make each thread calculation unique (e.g. item id and quantity equal to 1 to 100 - array index + 1). Although this accomplishes the first task of automating the requests, each thread must complete serially making the net result of the application performance exactly that of having the main thread executing one availability process 100 times (see &lt;a href="http://crossedlogic.abdu-shahid.com/java/aot/arrayofthreads_out.txt"&gt;output example 1&lt;/a&gt;: processing times go in sequence and so total processing time is long).&lt;br /&gt;&lt;br /&gt;In addition, this will most likely crash your application and/or back-end systems as user quantity requirements scale upward.&lt;br /&gt;&lt;br /&gt;I know this is not very practical for the use case we are exploring, but another component of the application I wrote was used to keep statistics on requests for availability. These statistics were needed for later analysis and did not need to be sent back to user. Applying the methodology of thread arrays for background processing that needs to be done at some point is a perfect fit. User leaves the site or at least is satisfied by a response, while additional business logic is applied as more data is gathered and stored in a business intelligence/reporting back-end.&lt;br /&gt;&lt;br /&gt;Thread pooling or utilizing all the threads simultaneously would answer both the automation of user process and most efficient run time concerns. See next post in the concurrent threading series for a detail on the ArrayOfThreadsPooled object included in the source code available for download above. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-43777090475124743?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/43777090475124743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=43777090475124743' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/43777090475124743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/43777090475124743'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/08/10000-threads-are-better-than-one.html' title='10,000 Threads Are Better Than One'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-3628082423106759319</id><published>2007-08-30T16:48:00.000-04:00</published><updated>2007-08-31T09:11:24.305-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concurrent threading series'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j#'/><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>The Adventure Begins (Concurrent Threading Series)</title><content type='html'>Multi-threading background processes is very cool for spawning large calculations that write to statistical/business intelligence data stores while responding other data quickly to user from the main thread; however, when you need to do some medium to long running calculations multiple times and return a sorted/combined result set to your user without feeding into the attention deficit disorder inside all of us, multi-threaded background processes become even cooler.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Background&lt;/span&gt;&lt;br /&gt;A practical or real life application for this would be an application that communicated with business systems (enterprise resource planning - inventory management in particular) to read current stock information, including current demand allocations; compare to new single demand; ultimately, displaying lead time to fulfill customer requirement whether from stock, assembling from stocked components on a bill of material, or purchasing/fabricating item through the portions if not all of its cumulative lead time.&lt;br /&gt;&lt;br /&gt;Furthermore, the delivery method on this application to client was via the web, so a few seconds processing time is a long wait to many, so response time must be considered in any alterations.&lt;br /&gt;&lt;br /&gt;Now consider a secondary request interface for this application that needs to determine separate responses for the same demand above.  This was used by Customer Service/Sales Representatives who need to know the breakdown of lead time(s) from satisfying quantity of one to the total requested.  As a customer, you may have an immediate need for five light bulbs or else you will be in darkness for the entire day, but you get cost efficiencies purchasing light bulbs in quantities of 1000.  The purpose of this extension to the availability service is to allow you as the customer understand that you can get 50 from stock today, 250 built within a week, and 700 available two months from now.  This is much more useful to satisfying both business needs than getting one response that indicates to get a complete order 1000 would be two months.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Problem&lt;/span&gt;&lt;br /&gt;Several months ago, during a migration from one business enabling system to another, I was faced with a need to architect this concurrent programming accomplished in Java as a .NET application.  My initial thought was to leverage and reuse as much of the Java code I had already written to lessen the development cycle for this change and to ensure that the logic was implemented as close to original as possible then improve from there once integration was established.  What did this mean?  Microsoft J# to the rescue!  Or at least so I hoped.&lt;br /&gt;&lt;br /&gt;Microsoft’s J# does not support Java 5.0 as it is based on previous JRE version.  This road blocked the effort immensely as it was not clear to me if Microsoft .NET even had the capability to perform the same concurrency programming and/or how, and so began the adventure to acquire knowledge.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Adventure&lt;/span&gt;&lt;br /&gt;The following set of posts try to go through thought process behind the multi-threading being done in the original Java implementation and hopefully arrive at the most efficient means of transforming to a .NET implementation.  Whether or not my journey to converting from Java to .NET is successful, I figured this information may be helpful for new (or at least new to threading) developers that are looking for methodologies to accomplish what I have done in either language.&lt;br /&gt;&lt;br /&gt;So buckle up and let’s explore together the migration of concurrent processing code from Java technology to J# and .NET in general.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-3628082423106759319?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/3628082423106759319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=3628082423106759319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3628082423106759319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/3628082423106759319'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/08/multi-threading-background-processes-is.html' title='The Adventure Begins (Concurrent Threading Series)'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38916088.post-242398209021068501</id><published>2007-06-18T15:05:00.000-04:00</published><updated>2007-09-06T18:31:44.660-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='vb.net'/><title type='text'>Deleting Multiple Views/Tables by Pattern in Microsoft SQL Server</title><content type='html'>If you have ever used Microsoft SQL Server tools to work with tables and/or views you will know that you cannot select multiple items for deletion (or at least not that I have found) through the UI. A good feature to ensure a unsuspecting user doesn't accidentally delete all the data from your production server, right?&lt;br /&gt;&lt;br /&gt;Well, suppose you needed to delete 4000+ views from an application database that didn't belong there (long story).&lt;br /&gt;&lt;br /&gt;The views all start with the same beginning text so they are right next to each other in the UI for SQL. Now the great feature is the bane of your existence as you hit delete, then confirm, delete, then confirm...&lt;br /&gt;&lt;br /&gt;Here is one solution you can use with some simple VB.NET code.&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; PATTERNS() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = {&lt;span class="str"&gt;"prefix1%"&lt;/span&gt;, &lt;span class="str"&gt;"prefix2%"&lt;/span&gt;, &lt;span class="str"&gt;"prefix3%"&lt;/span&gt;}&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; strDatasource &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = _&lt;br /&gt;&lt;span class="str"&gt;"Data Source=dbsvr;Initial Catalog=db;User ID=usr;Password=pwd"&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; strSqlStatement &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = _&lt;br /&gt;&lt;span class="str"&gt;"SELECT name FROM sys.sysobjects WHERE (name LIKE '"&lt;/span&gt; &amp;amp; PATTERNS(0) &amp;amp; _&lt;br /&gt;&lt;span class="str"&gt;"' OR name LIKE '"&lt;/span&gt; &amp;amp; PATTERNS(1) &amp;amp; &lt;span class="str"&gt;"' OR name LIKE '"&lt;/span&gt; &amp;amp; PATTERNS(2) &amp;amp; _&lt;br /&gt;&lt;span class="str"&gt;"') AND (xtype = 'V')"&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;'To make this flexible,&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;'you can loop through count of patterns items instead of hard coded usage&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; sqlConnection &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; SqlClient.SqlConnection(strDatasource)&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; sqlCommand &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; SqlClient.SqlCommand(strSqlStatement, sqlConnection)&lt;br /&gt;&lt;br /&gt;   sqlConnection.Open()&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; rs &lt;span class="kwrd"&gt;As&lt;/span&gt; SqlClient.SqlDataReader = sqlCommand.ExecuteReader()&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; namelist &lt;span class="kwrd"&gt;As&lt;/span&gt; ArrayList = &lt;span class="kwrd"&gt;New&lt;/span&gt; ArrayList()&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;While&lt;/span&gt; rs.Read()&lt;br /&gt;       namelist.Add(rs(&lt;span class="str"&gt;"name"&lt;/span&gt;).ToString)&lt;br /&gt;   &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;While&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   rs.Close()&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; count &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0&lt;br /&gt;   &lt;span class="kwrd"&gt;Dim&lt;/span&gt; names() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = _&lt;br /&gt;&lt;span class="kwrd"&gt;CType&lt;/span&gt;(namelist.ToArray(&lt;span class="kwrd"&gt;GetType&lt;/span&gt;(&lt;span class="kwrd"&gt;String&lt;/span&gt;)), &lt;span class="kwrd"&gt;String&lt;/span&gt;())&lt;br /&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;For&lt;/span&gt; i = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; (names.Length - 1)&lt;br /&gt;       &lt;span class="kwrd"&gt;If&lt;/span&gt; names(i).ToString &amp;lt;&amp;gt; &lt;span class="str"&gt;""&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;&lt;br /&gt;           sqlCommand.CommandText = _&lt;br /&gt;&lt;span class="str"&gt;"DROP VIEW [dbo].["&lt;/span&gt; &amp;amp; names(i) &amp;amp; &lt;span class="str"&gt;"]"&lt;/span&gt;&lt;br /&gt;           count += sqlCommand.ExecuteNonQuery()&lt;br /&gt;       &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;&lt;br /&gt;   &lt;span class="kwrd"&gt;Next&lt;/span&gt; i&lt;br /&gt;&lt;br /&gt;   sqlConnection.Close()&lt;br /&gt;   sqlCommand = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;&lt;br /&gt;   rs = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;&lt;br /&gt;   sqlConnection = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;&lt;br /&gt;   System.Console.WriteLine(count &amp;amp; &lt;span class="str"&gt;" affected!"&lt;/span&gt;)&lt;br /&gt;   System.Threading.Thread.Sleep(5000)&lt;br /&gt;   &lt;span class="kwrd"&gt;Return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This was done quick and dirty as a command line application and so I used the console to write the number of objects actually affected by script. The &lt;em&gt;Thread.Sleep(5000)&lt;/em&gt; was used to delay the console screen 5 secs on screen before going away so I could see the result.&lt;br /&gt;&lt;br /&gt;This was quick and dirty, so for a production utility, you may want to add other features like exception handling, input validation, and backout capabilities. Input validation would be very key if the program is modified to take a user supplied pattern versus the hard-coded method above. The worry is that someone will send '%' and wipe entire set of views/tables by accident.&lt;br /&gt;&lt;br /&gt;Anyway, the script uses the .NET objects for SQL connections to execute a bit of T-SQL which searches the sysobjects table for all the objects that match have a name like 'pattern' and xtype = 'V', restricting search to just views.&lt;br /&gt;&lt;br /&gt;Since it is not known the total number to be found, I have opted to use an ArrayList (Vector) approach to allow me to add 0 to many results. Later, the ArrayList is converted to an array of strings which is in turn used in a loop to create dynamic drop statements that are executed on the same SQL server that was queried for the object list in the first place.&lt;br /&gt;&lt;br /&gt;Hopefully this helps some poor DBA hitting the delete button 100 times at least once and I will be happy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38916088-242398209021068501?l=crossedlogic.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://crossedlogic.blogspot.com/feeds/242398209021068501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38916088&amp;postID=242398209021068501' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/242398209021068501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38916088/posts/default/242398209021068501'/><link rel='alternate' type='text/html' href='http://crossedlogic.blogspot.com/2007/06/deleting-multiple-viewstables-by.html' title='Deleting Multiple Views/Tables by Pattern in Microsoft SQL Server'/><author><name>kccjr2</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_OhPQeKhdpOA/TF2ZnQWrQUI/AAAAAAAAAB8/1BIqhjEJo3E/S220/lkyler_0307091308.jpg'/></author><thr:total>0</thr:total></entry></feed>
