<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Rob Farley : sql</title><link>http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx</link><description>Tags: sql</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Apostrophes around column aliases</title><link>http://msmvps.com/blogs/robfarley/archive/2009/12/29/apostrophes-around-column-aliases.aspx</link><pubDate>Mon, 28 Dec 2009 22:14:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1747471</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1747471</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/12/29/apostrophes-around-column-aliases.aspx#comments</comments><description>&lt;p&gt;Far too often I see SQL code which uses apostrophes around column aliases, like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;SELECT ProductID, SUM(LineTotal) AS &amp;#39;Total&amp;#39;       &lt;br /&gt;FROM Sales.SalesOrderDetail        &lt;br /&gt;GROUP BY ProductID;&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is fine, but the worrying thing about this is if the user decides to use this alias in an outer query. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;SELECT &amp;#39;ID&amp;#39;, &amp;#39;Total&amp;#39;       &lt;br /&gt;FROM        &lt;br /&gt;(        &lt;br /&gt;SELECT ProductID AS &amp;#39;ID&amp;#39;, SUM(LineTotal) AS &amp;#39;Total&amp;#39;        &lt;br /&gt;FROM Sales.SalesOrderDetail        &lt;br /&gt;GROUP BY ProductID        &lt;br /&gt;) AS p        &lt;br /&gt;;&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here, the outer query will assume that &amp;lsquo;ID&amp;rsquo; and &amp;lsquo;Total&amp;rsquo; are strings, not the names of columns in sub-query. It&amp;rsquo;s really not pretty. The query runs, but doesn&amp;rsquo;t give the correct answers. Furthermore, if this had&amp;rsquo;ve been done in a GROUP BY clause, or a JOIN, etc, then the error may have been hidden some more. An error might have occurred, but only in certain circumstances.&lt;/p&gt;
&lt;p&gt;What should have been done is to have used square brackets, like [Total], or even no brackets at all. Using the table alias in the outer query would have helped too.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;SELECT p.ID, p.Total       &lt;br /&gt;FROM        &lt;br /&gt;(        &lt;br /&gt;SELECT ProductID AS ID, SUM(LineTotal) AS Total        &lt;br /&gt;FROM Sales.SalesOrderDetail        &lt;br /&gt;GROUP BY ProductID        &lt;br /&gt;) AS p        &lt;br /&gt;;&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m not sure why SQL Server allows apostrophes to be used around column aliases, but unfortunately it does (and because it does now, it likely always will, if only to maintain backward-compatibility). So instead, any time you see code that uses apostrophes this way, please change it &amp;ndash; just to help any developers that come after you who don&amp;rsquo;t understand where things can fall down.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1747471" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category></item><item><title>Useful SQL Question and Answer sites</title><link>http://msmvps.com/blogs/robfarley/archive/2009/12/24/useful-sql-question-and-answer-sites.aspx</link><pubDate>Thu, 24 Dec 2009 05:14:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1747452</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1747452</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/12/24/useful-sql-question-and-answer-sites.aspx#comments</comments><description>&lt;p&gt;There are so many places to ask a question these days. I get plenty of questions via MSN Msgr and email, and do my best to answer those of course. But there are many others too. I figured I’d list some of the ones that I frequent, and challenge some of the readers here to check some of them out.&lt;/p&gt;  &lt;p&gt;The &lt;a href="http://social.msdn.microsoft.com/forums" target="_blank"&gt;MSDN Forums&lt;/a&gt; are terrific. Lots of really good people hang out there, including many Microsoft staff. They’re effectively the new version of the public newsgroups. It’s definitely worth asking (and answering) questions here, and I should probably choose this option more for answering questions myself.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.experts-exchange.com" target="_blank"&gt;Experts-Exchange&lt;/a&gt; is a much-maligned site, largely because to ask questions you need to have points. You can get points through a paid subscription, but you can also get points by answering questions. If you answer just a few questions each month, you can become a recognised Expert on the site, which lets you ask as many questions as you like, and also gives you the option of a “ad-free” environment. Many people still joke about the way that the site reads if you ignore the hyphen, but if you are an expert, this site is definitely worth hanging out on. You can register for free (getting you no points to ask questions until you’ve started answering them) at &lt;a href="http://www.experts-exchange.com/registerFree2.jsp"&gt;http://www.experts-exchange.com/registerFree2.jsp&lt;/a&gt;, so why not go there and register, so that you can start answering questions. They have a facility so that Designated Experts can get emails for neglected questions, giving you a much better chance of an answer than many other sites around. (Note – if you are a SQL MVP, or a MS employee, and you want to be fast-tracked into receiving the Neglected Questions notices, drop me a line and I’ll see what I can do for you)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.stackoverflow.com" target="_blank"&gt;Stack Overflow&lt;/a&gt; is a current favourite amongst many, because of the number of people that seem to frequent the site. It’s clean (very few adverts hanging around), and people seem to rush to answer questions as soon as possible. From a purely SQL perspective, I find that there is too much weighting on the iterative languages there, so many of the SQL responses seem to be provided by people who aren’t really SQL specialists. But it doesn’t mean that you won’t pick up some good tips there. I got started there by answering a &lt;a href="http://stackoverflow.com/questions/1176011/sql-to-determine-minimum-sequential-days-of-access/1176255#1176255" target="_blank"&gt;question that has even ended up in the source for the site&lt;/a&gt; – which I’m still hoping will reach the magical “100 up-votes”, and I’ve continued to keep my eye out for questions there that need answering.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.stackoverflow.com" target="_blank"&gt;Server Fault&lt;/a&gt; is the system administrator cousin to Stack Overflow. If you have DBA-style questions rather than developer-style, then this site is very useful. &lt;/p&gt;  &lt;p&gt;Using the same interface as Stack Overflow and Server Fault, but purely focussed on SQL Server is &lt;a href="http://ask.sqlservercentral.com" target="_blank"&gt;Ask SCC&lt;/a&gt;, run by the guys from &lt;a href="http://www.sqlservercentral.com" target="_blank"&gt;sqlservercentral.com&lt;/a&gt;. It’s a new players on the scene, but I think will turn into a very useful site. The Stack Overflow engine isn’t bad at all, and the quality of answer at Ask SCC is excellent. I would love to see more people hang out there, as it serves a useful market for SQL specialists. At the moment it doesn’t do much traffic, but many of the people there are good SQL experts, and I’m convinced that you’ll get an excellent answer if you ask a question there. At the moment it doesn’t seem to be collecting poor answers as much as many of the other sites, so the ratio of good answers to poor ones puts you in a good position as an asker. I’ve posted my Ask SCC and Stack Overflow ‘flairs’ here, so that you can compare the two. If the numbers on the Ask SCC one have reached as high as the Stack Overflow one, then you’ll have a good indication that the traffic on Ask SCC has increased nicely.&lt;/p&gt;  &lt;p&gt;&lt;iframe height="60" src="http://ask.sqlservercentral.com/users/flair/120.html?theme=default" frameborder="0" width="210" scrolling="no"&gt;&lt;/iframe&gt;&lt;iframe height="60" src="http://www.stackoverflow.com/users/flair/144351.html?theme=default" frameborder="0" width="210" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;  &lt;p&gt;In many ways, I tend to find that my efforts are focussed more on the questions that aren’t getting answered, rather than trying to catch the newest questions. On many of these sites, I’d rather find the one that the asker has had trouble with, hoping to provide the elusive answer rather than the obvious one. That question that got me started on Stack Overflow was an exception because I didn’t feel like any of the previous answers had really solved the question properly, but on the whole, my approach to Stack Overflow doesn’t really fit with most of the answerers on the site. I like EE because there really seems to be a focus on getting those elusive answers for people, and I know that Microsoft really focuses on getting answered questions sorted on their forums.&lt;/p&gt;  &lt;p&gt;My challenge to you is to give back to the community this Christmas. Make it a resolution for 2010 if you will. Why not try to answer a question every week? And better still, make it one that everyone else has had trouble answering. Go to the lists of unanswered questions, and help someone out. Next time it might be you asking, and you’ll hope that someone takes the time to find your elusive question.&lt;/p&gt;  &lt;p&gt;Plus, you might learn something!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1747452" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/community/default.aspx">community</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category></item><item><title>Infinite Drill-through in a single SSRS report</title><link>http://msmvps.com/blogs/robfarley/archive/2009/12/21/infinite-drill-through-in-a-single-ssrs-report.aspx</link><pubDate>Mon, 21 Dec 2009 10:18:15 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1746973</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1746973</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/12/21/infinite-drill-through-in-a-single-ssrs-report.aspx#comments</comments><description>&lt;p&gt;Grant Paisley of Angry Koala and Report Surfer put me onto this a while back, and I have to admit I’m a bit of a fan. The idea comes from the fact the way that SQL Server Reporting Services (both 2005 and 2008) handles parameters with Analysis Services, and lets you make a report that drills through into itself, deeper and deeper into a hierarchy. Today I did a talk at the Adelaide SQL Server User Group, and mentioned this was possible (but didn’t have the time to demonstrate it properly).&lt;/p&gt;  &lt;p&gt;If you make a parameterized query in an MDX query in SSRS, you use the STRTOMEMBER or STRTOSET function to handle this. But the MDX has no other indication of what dimension, hierarchy or level is being passed in. If you grab the children of whatever you’ve passed in, you can easily put this on the Rows axis and get one level down. Passing the UniqueName of whatever you’ve just provided back in as the next parameter, and you have infinite drill-through.&lt;/p&gt;  &lt;p&gt;Look at the following MDX query:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;WITH        &lt;br /&gt;MEMBER [Measures].[NextLevel] as StrToMember(@SomeDate).Hierarchy.CurrentMember.UniqueName        &lt;br /&gt;MEMBER [Measures].[NextLevel Name] as StrToMember(@SomeDate).Hierarchy.CurrentMember.Member_Name &lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;em&gt;SELECT        &lt;br /&gt;NON EMPTY { [Measures].[Internet Sales Amount], [Measures.NextLevel], [Measures].[NextLevel Name] } ON COLUMNS,         &lt;br /&gt;NON EMPTY { (StrToMember(@SomeDate).Children ) } ON ROWS &lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;em&gt;FROM [Adventure Works] &lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You see that I provide the UniqueName and Member_Name properties in known columns, so that I can easily reference them in my report. You’ll also notice that nowhere do I actually indicate which dimension I’m planning to drill down on, or to which hierarchy the @SomeDate parameter refers. I have suggested it’s a date, but only in name. At this point I also make sure that the Report Parameter is not restricted to values from a particular query, and I hide it from the user. I’m going to be passing in UniqueName values, which aren’t particular user-friendly.&lt;/p&gt;  &lt;p&gt;If I start with [Date].[Fiscal].[Fiscal Year].&amp;amp;[2003], then my NextLevels will be [Date].[Fiscal].[Fiscal Semester].&amp;amp;[2003]&amp;amp;[1] and [Date].[Fiscal].[Fiscal Semester].&amp;amp;[2003]&amp;amp;[2]. This then continues down as far as I want it to go. I could always put a condition on my Action to pick up when there are no more levels, and potentially start down a different hierarchy. After all, I can always use a bunch of other parameters in the WHERE clause to slice the cube in other ways first, for placeholders. It really just comes down to MDX creativity to investigate different ways of drilling through the data.&lt;/p&gt;  &lt;p&gt;Please bear in mind that other people may well have achieved the same sort of thing using a different query – I’m just posting what has worked for me. Hopefully by doing this, you can avoid making five drill-through reports just because your hierarchy has five levels. This might just remove 80% of your reporting effort!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1746973" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/adssug/default.aspx">adssug</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/reporting+services/default.aspx">reporting services</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/ssas/default.aspx">ssas</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/mdx/default.aspx">mdx</category></item><item><title>High ROI items for SQL Server 2008</title><link>http://msmvps.com/blogs/robfarley/archive/2009/12/18/high-roi-items-for-sql-server-2008.aspx</link><pubDate>Thu, 17 Dec 2009 23:02:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1745828</guid><dc:creator>Rob Farley</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1745828</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/12/18/high-roi-items-for-sql-server-2008.aspx#comments</comments><description>&lt;p&gt;To persuade your boss to embrace an upgrade to SQL 2008, you need to know which features have high Return On Investment. They may have seen presentations talking about features like Spatial, or MERGE (and been quite impressed), but they may well have left those presentations thinking about the effort that’s would be involved in rewriting applications to take advantage of these features. It’s all well and good to see your customers on a map, but someone has to make that spatial data appear somewhere.&lt;/p&gt;  &lt;p&gt;This post is a callout for features that will benefit you (and your boss) as soon as you do the upgrade (or soon after). And I welcome comments to list other items as well.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Block Computation &lt;/strong&gt;(in SSAS – which reduces the effort in processing significantly, for no change in the application )&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Transparent Data Encryption &lt;/strong&gt;(in the Database Engine – which makes sure that data at rest is encrypted, with no change in the application)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Backup Compression &lt;/strong&gt;(which reduces the size of backups, and can be set as the default so that existing backup scripts don’t need to change)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Data Compression &lt;/strong&gt;(minimal change to turn on compression on tables which will compress nicely)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Filtered Indexes &lt;/strong&gt;(because how far off is your next index creation, really?)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Auditing &lt;/strong&gt;&amp;amp; &lt;strong&gt;Change Data Tracking &lt;/strong&gt;(because it’s very easy to turn on and then review the data as you need it)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Export to Word in SSRS &lt;/strong&gt;(because everyone’s wanted this for so long)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;SSRS paging &lt;/strong&gt;(because SSRS used to get _all_ the data for a report before rendering it – but not in 2008)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Resource Governor&lt;/strong&gt; (easy to set up, nice to have in place for when you might want it)&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Hot-add memory&lt;/strong&gt; (so that you can just plug in more memory without having to do restarts)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’m not suggesting that an upgrade should be done flippantly. You should still consider the effort of thoroughly testing your system under SQL 2008. But hopefully this list can highlight some of the things that I’ve found are good persuaders. A list of “What’s New in SQL 2008” can be found at &lt;a title="http://www.microsoft.com/sqlserver/2008/en/us/whats-new.aspx" href="http://www.microsoft.com/sqlserver/2008/en/us/whats-new.aspx"&gt;http://www.microsoft.com/sqlserver/2008/en/us/whats-new.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Like I said, you may have other items on your own list, and I invite you to comment on this. You may also have things in place to handle things like encryption, and you may be running Hyperbac or one of the other compression tools.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1745828" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+server+2008/default.aspx">sql server 2008</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+improvements/default.aspx">sql improvements</category></item><item><title>T-SQL Tuesday – A date dimension table with computed columns</title><link>http://msmvps.com/blogs/robfarley/archive/2009/12/08/t-sql-tuesday-a-date-dimension-table-with-computed-columns.aspx</link><pubDate>Tue, 08 Dec 2009 08:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1743741</guid><dc:creator>Rob Farley</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1743741</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/12/08/t-sql-tuesday-a-date-dimension-table-with-computed-columns.aspx#comments</comments><description>&lt;p&gt;Quite a few people have asked me to blog about what I do for a date dimension table. I&amp;rsquo;m talking about a table that Analysis Services references for a Time dimension. It&amp;rsquo;s going to contain every date in a particular range, and be flexible enough to cater for public holidays and other custom details.&lt;/p&gt;
&lt;p&gt;There are plenty of options for this, and I&amp;rsquo;ll mention some of them a bit later. What I use most of the time is an actual table in the Data Warehouse, which I populate with a row for each date in the range I want to consider. This range starts well before the earliest date I could want, and I don&amp;rsquo;t leave gaps either. Some people like to only use dates that have fact data, but I prefer to have the dates going back as far as I like.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk about what the table looks like, and then how it can be created.&lt;/p&gt;
&lt;p&gt;I have a primary key on an integer based on the date, in the format YYYYMMDD. So today would have the number 20091208. I haven&amp;rsquo;t tried using the date type that&amp;rsquo;s available in SQL Server 2008 for a date dimension yet &amp;ndash; I generally try to use numbers for dimension keys, and haven&amp;rsquo;t tested the alternative yet. Using an integer like this for the key in a date dimension is generally considered best practice.&lt;/p&gt;
&lt;p&gt;I also have a column which is the actual date itself. I will use this as the Value column for the dimension key in Analysis Services. I also have various representations of the date in string form, such as &amp;ldquo;Tuesday December 8th, 2009&amp;rdquo;, &amp;ldquo;08/12/2009&amp;rdquo;, &amp;ldquo;8-Dec-2009&amp;rdquo;. One of these will be the Name column, but I may have others available for other properties and translations. A &amp;ldquo;12/08/2009&amp;rdquo; option may be preferable for a US translation, for example.&lt;/p&gt;
&lt;p&gt;Columns in my table should indicate which year it is, such as 2009. I&amp;rsquo;ll also throw in the start of the year (in a date format), and something which indicates which Financial Year it is. In Australia, this is most easily handled by adding six months onto the current date and considering the year of this adjusted date (our FY starts on July 1st). I can subtract the six months back again to work out what the start of the Financial Year is. I try to keep things in the code quite simple, as I leave this code with the client and hope they can maintain it as required. The trickiest I get is to use the DATEADD(month,DATEDIFF(month,0,ActualDate),0) technique for truncation, but I think this should be required knowledge when handling dates.&lt;/p&gt;
&lt;p&gt;For months, quarters, semesters, weeks, and so on, I will also prefer to have an integer as the key. A Month Key would take the format 200912 for this month, or 201001 for next month. Quarters can be done using 20094 and 20101, and so on.&lt;/p&gt;
&lt;p&gt;This may all seem quite complex, but it&amp;rsquo;s something you only need to do one time.&lt;/p&gt;
&lt;p&gt;Let me explain&amp;hellip;&lt;/p&gt;
&lt;p&gt;My table only really contains one field. Yes, just one. More might be required for custom fields, but where possible, I will just populate one field and let all the rest be handled using computed columns.&lt;/p&gt;
&lt;p&gt;Even the primary key will be a computed column.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;CREATE TABLE dbo.Dates (       &lt;br /&gt;&amp;nbsp; DateKey AS CONVERT(int, CONVERT(char(8), ActualDate, 112)) PERSISTED NOT NULL        &lt;br /&gt; ,ActualDate DATETIME NOT NULL         &lt;br /&gt; ,CalendarYearKey AS YEAR(ActualDate) PERSISTED NOT NULL        &lt;br /&gt; ,CalendarYearName AS CONVERT(char(4), YEAR(ActualDate)) PERSISTED NOT NULL        &lt;br /&gt; ,CalendarYearStart AS DATEADD(year,DATEDIFF(year,0,ActualDate),0) PERSISTED NOT NULL        &lt;br /&gt; ,FinancialYearKey AS YEAR(DATEADD(month,6,ActualDate)) PERSISTED NOT NULL        &lt;br /&gt; ,FinancialYearName AS CONVERT(char(4),YEAR(DATEADD(month,6,ActualDate))-1) + &amp;#39;/&amp;#39; + RIGHT(CONVERT(char(4),YEAR(DATEADD(month,6,ActualDate))),2) PERSISTED NOT NULL        &lt;br /&gt; ,FinancialYearStart AS DATEADD(month,-6,DATEADD(year,DATEDIFF(year,0,DATEADD(month,6,ActualDate)),0)) PERSISTED NOT NULL         &lt;br /&gt; ,MonthKey AS CONVERT(int, CONVERT(char(6),ActualDate,112)) PERSISTED NOT NULL        &lt;br /&gt; ,MonthName AS CASE MONTH(ActualDate)        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 1 then &amp;#39;Jan&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 2 then &amp;#39;Feb&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 3 then &amp;#39;Mar&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 4 then &amp;#39;Apr&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 5 then &amp;#39;May&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 6 then &amp;#39;Jun&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 7 then &amp;#39;Jul&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 8 then &amp;#39;Aug&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 9 then &amp;#39;Sep&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 10 then &amp;#39;Oct&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 11 then &amp;#39;Nov&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 12 then &amp;#39;Dec&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; END        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + &amp;#39; &amp;#39; + CONVERT(char(4), YEAR(ActualDate)) PERSISTED NOT NULL        &lt;br /&gt; ,FrenchMonthName AS CASE MONTH(ActualDate)        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 1 THEN &amp;#39;janv&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 2 THEN &amp;#39;f&amp;eacute;vr&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 3 THEN &amp;#39;mars&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 4 THEN &amp;#39;avr&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 5 THEN &amp;#39;mai&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 6 THEN &amp;#39;juin&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 7 THEN &amp;#39;juil&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 8 THEN &amp;#39;ao&amp;ucirc;t&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 9 THEN &amp;#39;sept&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 10 THEN &amp;#39;oct&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 11 THEN &amp;#39;nov&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN 12 THEN &amp;#39;d&amp;eacute;c&amp;#39;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; END        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + &amp;#39; &amp;#39; + CONVERT(char(4), YEAR(ActualDate)) PERSISTED NOT NULL        &lt;br /&gt;--Many more columns following        &lt;br /&gt;);        &lt;br /&gt;GO&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You will notice that I have used ugly long CASE statements for the MonthName columns. I do the same for the names of the days of the week. The reason is betrayed in the second example. DATENAME (or any kind of conversion that relies upon the language setting, such as CONVERT(char(3),ActualDate,100)) is non-deterministic, and therefore can&amp;rsquo;t be used in a persisted computed column (I do wish that CONVERT could take a Language setting, so that I could tell it to convert in English, French, etc, and make it deterministic). Why do I want them to persist? Well&amp;hellip; I&amp;rsquo;m just more comfortable with them being persisted. After all, I could use a view for the whole thing at this stage, but I&amp;rsquo;m really not that comfortable with the table being generated on the fly when it comes to processing. The table is essentially read-only, after all.&lt;/p&gt;
&lt;p&gt;As well as many computed columns like this, I will also have some that are not computed, such as a column to indicate if it&amp;rsquo;s a public holiday. This could be computed, at a push, as public holidays generally follow a system. Even Easter follows a formula that could be applied. But if the company takes a special day, or if government declares an extra day for some reason, then problems can start popping up. I find it convenient to have columns that can be updated directly (but which have defaults, of course).&lt;/p&gt;
&lt;p&gt;One great thing about this method is that it can be populated very easily. The only field you insert data into is the ActualDate column. Generating a list of dates is as easy as using DATEADD() with a nums table, as I&amp;rsquo;ve written many times before, including this &lt;a href="http://stackoverflow.com/questions/1378593/get-a-list-of-dates-between-two-dates-using-a-function/1378788#1378788" target="_blank"&gt;StackOverflow question&lt;/a&gt;. If you need more dates, just insert more. &lt;/p&gt;
&lt;p&gt;As I mentioned before, a view could be used for this. It is very easy to generate a list of dates, and then all the other calculations could be done as other columns in the view. You could perform an OUTER JOIN into a table which lists public holidays and other special days. Analysis Services will happily handle this in much the same way. I just prefer to have it exist as a table, which I feel I have more control over.&lt;/p&gt;
&lt;p&gt;This post has been part of T-SQL Tuesday, hosted this month by &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/11/30/invitation-to-participate-in-t-sql-tuesday-001-date-time-tricks.aspx" target="_blank"&gt;Adam Machanic&lt;/a&gt;. You should be able to see many other posts related to datetime mentioned as Trackbacks to Adam&amp;rsquo;s post.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1743741" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/ssas/default.aspx">ssas</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/t-sql+tuesday/default.aspx">t-sql tuesday</category></item><item><title>Dangers of BEGIN and END</title><link>http://msmvps.com/blogs/robfarley/archive/2009/12/05/dangers-of-begin-and-end.aspx</link><pubDate>Sat, 05 Dec 2009 11:32:47 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1743773</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1743773</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/12/05/dangers-of-begin-and-end.aspx#comments</comments><description>&lt;p&gt;I’ve presented this material at three conferences recently, so it’s about time I wrote a blog post on it...&lt;/p&gt;  &lt;p&gt;As programmers, we love modularisation – even in the SQL space. We make stored procedures, views, and functions to encapsulate our code. This improves maintainability, simplifies the development experience, and is generally useful.&lt;/p&gt;  &lt;p&gt;But there’s a time when it’s a bad thing for SQL Server.&lt;/p&gt;  &lt;p&gt;There’s an amazing component of SQL Server called the Query Optimizer (I always want to write Optimiser, but I’m assuming it’s a proper noun and putting up with the US spelling). When we write queries in T-SQL, it’s the Query Optimizer that works out how to actually run the query. It works out what indexes can be used to improve performance, what order tables (well, indexes and heaps) should be accessed, how to perform the joins, and so on. I find that a rough appreciation of the power of the Query Optimizer can really help query writers.&lt;/p&gt;  &lt;p&gt;For example, the Query Optimizer will translate a correlated sub-query in the SELECT clause into a LEFT OUTER JOIN, so that &lt;a href="http://stackoverflow.com/questions/1772609/procedurally-transform-subquery-into-join/1844502#1844502" target="_blank"&gt;you don’t have to&lt;/a&gt;. It will also work out when joins can be rendered pointless and thereby &lt;a href="http://go2.wordpress.com/?id=725X1342&amp;amp;site=philnolan.wordpress.com&amp;amp;url=http%3A%2F%2Fmsmvps.com%2Fblogs%2Frobfarley%2Farchive%2F2008%2F11%2F09%2Fjoin-simplification-in-sql-server.aspx" target="_blank"&gt;removed from the plan altogether&lt;/a&gt;. If you let these principles help you in your query design, you can see significant benefits. It also helps you write queries that are easier to maintain, as there’s little point in trying to be clever by writing a query in a different way if the Query Optimizer will handle it in the same way as before.&lt;/p&gt;  &lt;p&gt;If you use a view in another query, the definition of the view is used in the query as if you had written it with a sub-query. A view is simply that – a stored sub-query. They are sometimes referred to as ‘virtual tables’, but I disagree. They are stored sub-queries. Sure, the analogy falls down when you start considering indexed views, but on the whole, a view should be seen as a stored sub-query. The Query Optimizer takes the view definition, applies it in the second query, simplifies it where possible, and works out the best way of executing it. If you’re only interested in a couple of columns out of the view, the Query Optimizer has an opportunity to take that into consideration.&lt;/p&gt;  &lt;p&gt;Stored procedures are different. You can’t use a stored procedure in an outer query. The closest you can get to this is to use OPENROWSET to consume the results of a stored procedure in an outer query, but still the whole procedure runs. After all, it’s a procedure. A set of T-SQL &lt;strong&gt;commands&lt;/strong&gt;, not a set of queries. I see the clue to this as the BEGIN and END that stored procedures generally use. I like stored procedures, but I do get frustrated if they’re returning more information than I need, since I have no way of letting the system know that maybe it doesn’t need to do as much work.&lt;/p&gt;  &lt;p&gt;Functions are in between, and come in two varieties. A function can be inline, or it can be procedural. I don’t think you find this differentiation in many places – and normally people talk about this particular drawback as being associated with Scalar Functions as compared to Table-Valued Functions, but the problem is actually one of simplification.&lt;/p&gt;  &lt;p&gt;An inline function must be a table-valued function at this point in time. It takes the form:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;CREATE FUNCTION dbo.fnFunctionName(&amp;lt;paramlist&amp;gt;) RETURNS TABLE AS       &lt;br /&gt;RETURN        &lt;br /&gt;( SELECT …. );&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It is always this form, with a sub-query enclosed in a RETURN statement. It can return many columns and many rows, but the definition of the table is implied by the SELECT clause. This is essentially a view that can take parameters.&lt;/p&gt;  &lt;p&gt;The other form is one that involves BEGIN and END. Scalar functions (unfortunately) require this (but hopefully one day will not).&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;CREATE FUNCTION dbo.fnFunctionName(&amp;lt;paramlist&amp;gt;) RETURNS int AS       &lt;br /&gt;BEGIN        &lt;br /&gt;RETURN ( ... )        &lt;br /&gt;END;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As the RETURN statement is enclosed between a BEGIN and END, it can be preceded by other statements, used in working out what value should be returned.&lt;/p&gt;  &lt;p&gt;Table-valued functions can use BEGIN and END, when multiple lines are required to calculate the rows in the table being returned.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;CREATE FUNCTION dbo.fnFunctionName(&amp;lt;paramlist&amp;gt;) RETURNS @table TABLE (&amp;lt;fields&amp;gt;) AS       &lt;br /&gt;BEGIN        &lt;br /&gt;...        &lt;br /&gt;RETURN        &lt;br /&gt;END;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In this kind of function, the table variable is populated with data, and returned to the outer query when the RETURN command is reached.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;But when the Query Optimizer comes across a procedural function, it cannot simplify it out and executes the function in a different context.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The execution plan will report that the cost of running the function is zero. But it’s lying. The way to see the impact of the function is to look in SQL Profiler, where you’ll see potentially many calls to the function, as it needs to work out the result for each different set of parameters it’s passed. The pain can be quite great, and you will never have noticed if you just look at the Execution Plans.&lt;/p&gt;  &lt;p&gt;The moral of the story is to make sure that your functions are able to be simplified out by the Query Optimizer. Use inline table-valued functions even in place of scalar functions. You can always hook into them using CROSS/OUTER APPLY in your FROM clause, or even use them in your SELECT clause (not “SELECT Claws” – that would make it related to my company LobsterPot Solutions, and “SELECT Claus” is just a bit Christmassy) using a construct like SELECT (SELECT field FROM dbo.fnMyTVF(someParam)) ...&lt;/p&gt;  &lt;p&gt;Consider the Query Optimizer your friend. Study Execution Plans well to look at how the Query Optimizer is simplifying your query. And stay away from BEGIN and END if possible.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1743773" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/wagga/default.aspx">wagga</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/teched/default.aspx">teched</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+bits/default.aspx">sql bits</category></item><item><title>StreamInsight talk coming up at SQLBits</title><link>http://msmvps.com/blogs/robfarley/archive/2009/11/20/streaminsight-talk-coming-up-at-sqlbits.aspx</link><pubDate>Fri, 20 Nov 2009 11:47:24 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1740965</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1740965</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/11/20/streaminsight-talk-coming-up-at-sqlbits.aspx#comments</comments><description>&lt;p&gt;My talk on &lt;a href="http://msdn.microsoft.com/en-us/library/dd631799%28SQL.10%29.aspx" target="_blank"&gt;StreamInsight&lt;/a&gt; is up next. I’ll try to blog more about that later. For now, I want to mention more about &lt;a href="http://www.sqlbits.com" target="_blank"&gt;SQLBits&lt;/a&gt; itself. This is by far the largest SQL-only conference I’ve attended (I haven’t been to SQL-PASS yet), and it’s great to be involved.&lt;/p&gt;  &lt;p&gt;Yesterday I had an all-day seminar about the new items for Developers in SQL 2008. It was a good time – the delegates responded very positively, and many of them have caught up with me since.&lt;/p&gt;  &lt;p&gt;But for me, the conference is being a great way of catching up with (and meeting for the first time) a bunch of SQL people that I rarely see. I’ve met people that lived only a few miles from where I grew up, and people that read my blog (Hi!), discovered people who have connections to Adelaide, and even found that my Adelaide friend Martin Cairney (who is also here) has a strange connection to Donald Farmer (of Microsoft), that their parents shared a back fence or something… Now Trevor Dwyer tells me a colleague of his knows me from somewhere… the world is very small here.&lt;/p&gt;  &lt;p&gt;My StreamInsight talk will be interesting I hope. I have some stuff to show off, and I plan to involve the audience a little as well. If you’re at SQLBits and feel like being involved in an interactive session, then definitely come along. I want to hear from people in the audience who have dabbled with StreamInsight and also other vendors’ Complex Event Processing offerings. This is a brand new technology from Microsoft, and there will be a large range of adoption levels in the room.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1740965" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/community/default.aspx">community</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+server+2008/default.aspx">sql server 2008</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+bits/default.aspx">sql bits</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/streaminsight/default.aspx">streaminsight</category></item><item><title>More SQL Conferences coming up, including SQL Bits and SQL Down Under</title><link>http://msmvps.com/blogs/robfarley/archive/2009/08/27/more-sql-conferences-coming-up-including-sql-bits-and-sql-down-under.aspx</link><pubDate>Thu, 27 Aug 2009 12:06:33 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1718698</guid><dc:creator>Rob Farley</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1718698</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/08/27/more-sql-conferences-coming-up-including-sql-bits-and-sql-down-under.aspx#comments</comments><description>&lt;p&gt;I know I won’t be there, as I’m a million miles away in Australia, but being from the UK myself, I always have an interest in the UK SQL community and in particular, events like SQL Bits.&lt;/p&gt;  &lt;p&gt;This is the fifth &lt;a href="http://www.sqlbits.com/" target="_blank"&gt;SQL Bits conference&lt;/a&gt;, and they keep getting larger and larger. I’ve heard it’s now the largest SQL-focussed event in Europe. It’s going to be in South Wales (&lt;a href="http://www.youtube.com/watch?v=SY-u15WmQBE" target="_blank"&gt;that’s OLD South Wales, not New South Wales&lt;/a&gt;), in November. I’m sure the area is lovely, good beaches ‘n all that… but considering it’s late November in Wales, I think you’ll be going for the SQL content, not the scenery.&lt;/p&gt;  &lt;p&gt;Of course, if you are in New South Wales, then you ought to be thinking slightly earlier, in particular, the second weekend in October. The third &lt;a href="http://www.sqldownunder.com/SDUCodeCamp/tabid/100/Default.aspx" target="_blank"&gt;SQL Code Camp&lt;/a&gt; is being held in Wagga, with many regular speakers (like myself) and quite a few new ones too.&lt;/p&gt;  &lt;p&gt;These two events are clearly the significant SQL events in the last quarter of the year. I’m sure no-one cares about &lt;a href="http://summit2009.sqlpass.org/" target="_blank"&gt;SQL PASS&lt;/a&gt;, after all. (I do wish I was going to this one, but I won’t be. I plan to go one year, but I was in the US that week last year, and I don’t plan to be away from home for two birthdays in a row. Maybe next year. It is the biggest SQL event in the world, with great speakers from everywhere, including many good friends of mine.)&lt;/p&gt;  &lt;p&gt;No matter where you are in the world, there are SQL events that you should be going to. Professional development is really important for your career, and you shouldn’t neglect it. That being said, make sure you find me at &lt;a href="http://www.msteched.com/australia/Public/default.aspx" target="_blank"&gt;TechEd Australia&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1718698" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/community/default.aspx">community</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/wagga/default.aspx">wagga</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/code+camp/default.aspx">code camp</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/professional+development/default.aspx">professional development</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+bits/default.aspx">sql bits</category></item><item><title>Still learning…  foreign keys don’t need to reference a primary key</title><link>http://msmvps.com/blogs/robfarley/archive/2009/08/05/still-learning-foreign-keys-don-t-need-to-reference-a-primary-key.aspx</link><pubDate>Tue, 04 Aug 2009 23:09:15 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1713056</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1713056</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/08/05/still-learning-foreign-keys-don-t-need-to-reference-a-primary-key.aspx#comments</comments><description>&lt;p&gt;…but you should still have a primary key on every table of course.&lt;/p&gt;  &lt;p&gt;It’s just that I only recently discovered that you can have a foreign key that references something else, so long as it’s known to be unique through a unique index / constraint.&lt;/p&gt;  &lt;p&gt;The scripts here demonstrate this in SQL Server 2005 and beyond.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;create table testunique (id int identity(1,1) primary key, otherid int);     &lt;br /&gt;go      &lt;br /&gt;create unique index ixOther on testunique(otherid);      &lt;br /&gt;go      &lt;br /&gt;create table testFK (id int identity(1,1) primary key, someid int)      &lt;br /&gt;go      &lt;br /&gt;alter table testFK add constraint fkTest foreign key (someid) references testunique(otherid)      &lt;br /&gt;go&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;And then if I try to drop the ixOther index, I get an error saying: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Msg 3723, Level 16, State 6, Line 1     &lt;br /&gt;An explicit DROP INDEX is not allowed on index &amp;#39;testunique.ixOther&amp;#39;. It is being used for FOREIGN KEY constraint enforcement.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So I guess this is another reason not to blindly remove indexes that aren’t mentioned in sys.dm_db_index_usage_stats&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1713056" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category></item><item><title>SSRS: Removing the Navigation link using an Expression</title><link>http://msmvps.com/blogs/robfarley/archive/2009/08/05/ssrs-removing-the-navigation-link-using-an-expression.aspx</link><pubDate>Tue, 04 Aug 2009 13:22:59 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1712792</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1712792</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/08/05/ssrs-removing-the-navigation-link-using-an-expression.aspx#comments</comments><description>&lt;p&gt;There are times when you want to have a Navigation property of a textbox (typically providing a link to a URL or other report), but you don’t always want the link to be there. Sometimes you just want it to be an ordinary textbox.&lt;/p&gt;  &lt;p&gt;This particularly applies when you’re using a Matrix, and you don’t want the Subtotal rows to have the navigation links. Previously I’ve &lt;a href="http://msmvps.com/blogs/robfarley/archive/2007/11/22/how-to-format-the-subtotals-of-a-reporting-services-matrix-differently-using-inscope.aspx" target="_blank"&gt;blogged about using InScope&lt;/a&gt; to control various properties. But the thing that I hadn’t noticed was how to make the link actually disappear. I could make it point at somewhere less useful (like the current report), but I didn’t want the cursor to change.&lt;/p&gt;  &lt;p&gt;And then my friend (and fellow MVP) &lt;a href="http://stratesql.com" target="_blank"&gt;Jason Strate&lt;/a&gt; told me that if you make the Expression give the result of “Nothing”, then this does the trick.&lt;/p&gt;  &lt;p&gt;So try something like: =iif(inscope(&amp;quot;matrix1_SalesPersonID&amp;quot;), “http://someurl.com”, Nothing)&lt;/p&gt;  &lt;p&gt;Thanks, Jason!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1712792" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/reporting+services/default.aspx">reporting services</category></item><item><title>Counting consecutive instances with DENSE_RANK</title><link>http://msmvps.com/blogs/robfarley/archive/2009/07/25/counting-consecutive-instances-with-dense-rank.aspx</link><pubDate>Fri, 24 Jul 2009 23:34:52 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1709227</guid><dc:creator>Rob Farley</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1709227</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/07/25/counting-consecutive-instances-with-dense-rank.aspx#comments</comments><description>&lt;p&gt;It’s hard to think of a practical use for DENSE_RANK(), but here’s one.&lt;/p&gt;  &lt;p&gt;It’s one of the ranking functions that was introduced in SQL Server 2005, along with RANK(), NTILE(n) and the incredibly useful ROW_NUMBER(). But apart from producing reports, it’s quite hard to find genuine uses for some of them.&lt;/p&gt;  &lt;p&gt;Yesterday I answered a question at StackOverflow (first time – I often answer questions at Experts Exchange and on the MSDN Forums, but never at StackOverflow before). It’s at &lt;a title="http://stackoverflow.com/questions/1176011/sql-to-determine-minimum-sequential-days-of-access/1176255#1176255" href="http://stackoverflow.com/questions/1176011/sql-to-determine-minimum-sequential-days-of-access/1176255#1176255"&gt;http://stackoverflow.com/questions/1176011/sql-to-determine-minimum-sequential-days-of-access/1176255#1176255&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The problem is trying to find runs of consecutive days of activity. I solved it using ROW_NUMBER() and the integer value of the day, grouping by the offset between them. When you partition the ROW_NUMBER() by the users, you have a complete solution. It works nicely.&lt;/p&gt;  &lt;p&gt;But if people can have multiple entries in a day, then ROW_NUMBER() doesn’t cut it – the offset would change whenever someone didn’t have exactly one record per day. Of course, there might be logic in place to make sure this never happens, and I hope there would be – but if there isn’t the problem just becomes one for DENSE_RANK().&lt;/p&gt;  &lt;p&gt;You see, DENSE_RANK() won’t go up for ties. If you have two entries on the same day, they’ll be given the same rank. And then the next day will be as if there had only been one the previous day. If you have ten 107ths, the next DENSE_RANK() is 108 (RANK() would give the next value as 117).&lt;/p&gt;  &lt;p&gt;So then my query of:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;with numberedrows as       &lt;br /&gt;(        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select row_number() over (partition by UserID order by CreationDate) - cast(CreationDate-0.5 as int) as TheOffset, CreationDate, UserID        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from tablename        &lt;br /&gt;)        &lt;br /&gt;select min(CreationDate), max(CreationDate), count(*) as NumConsecutiveDays, UserID        &lt;br /&gt;from numberedrows        &lt;br /&gt;group by UserID, TheOffset;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;…becomes:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;with numberedrows as       &lt;br /&gt;(        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select dense_rank() over (partition by UserID order by cast(CreationDate-0.5 as int)) - cast(CreationDate-0.5 as int) as TheOffset, CreationDate, UserID        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from tablename        &lt;br /&gt;)        &lt;br /&gt;select min(CreationDate), max(CreationDate), datediff(day, min(CreationDate), max(CreationDate)) + 1 as NumConsecutiveDays, count(*) as NumEntries, UserID        &lt;br /&gt;from numberedrows        &lt;br /&gt;group by UserID, TheOffset;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Bear in mind that I’m having to truncate the CreationDate here. If the values were stored as an date with no time component, I’d be able to use CreationDate without modification, which lends itself much better to indexing strategies. For this scenario, I’d prefer to have an index on a computed column which was the truncated date.&lt;/p&gt;  &lt;p&gt;So there you go – a practical use for DENSE_RANK().&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1709227" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category></item><item><title>The new brand is Microsoft SQL Azure</title><link>http://msmvps.com/blogs/robfarley/archive/2009/07/09/the-new-brand-is-microsoft-sql-azure.aspx</link><pubDate>Thu, 09 Jul 2009 11:57:12 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1698983</guid><dc:creator>Rob Farley</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1698983</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/07/09/the-new-brand-is-microsoft-sql-azure.aspx#comments</comments><description>&lt;p&gt;It used to be SQL Server Data Services. Then SQL Data Services. Then we started hearing about SQL Services, and now (I hope finally), we have Microsoft SQL Azure instead of SQL Services, and the Microsoft SQL Azure Database instead of SQL Data Services.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://blogs.technet.com/dataplatforminsider/archive/2009/07/08/microsoft-sql-services-is-now-microsoft-sql-azure.aspx" href="http://blogs.technet.com/dataplatforminsider/archive/2009/07/08/microsoft-sql-services-is-now-microsoft-sql-azure.aspx"&gt;http://blogs.technet.com/dataplatforminsider/archive/2009/07/08/microsoft-sql-services-is-now-microsoft-sql-azure.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I think this is a sensible move. For a while now, whenever refer to SQL Services, I have to make it clear that it’s not the Windows Services that run SQL on your server, but that it’s the “in the cloud” offering that Microsoft are bringing out. Now, I can talk about SQL Azure, and it’s very clear what it means. And SQL Azure Database is clear too, as opposed to whatever will come, like (and I’m predicting here, haven’t heard anything) SQL Azure Analytics or SQL Azure Reporting.&lt;/p&gt;  &lt;p&gt;This is definitely a positive move, and should hopefully help people realise that this is not the same as SQL Server, help them approach their SQL Azure platform slightly differently to their On-Premise equivalent. &lt;/p&gt;  &lt;p&gt;For example… At the moment, the SQL Azure Database platform is limited in size. I hope it will soon be unlimited, but for the time being there is a limit which will affect development decisions. If your database suddenly needs to store a lot more data than you expected, you may need to hurriedly work out how you’re going to handle this. But I think having a name which reflects the Azure nature will prompt developers into making this decision earlier.&lt;/p&gt;  &lt;p&gt;I’m looking forward to getting my hands on SQL Azure, and seeing how my job will change because of it.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1698983" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+azure/default.aspx">sql azure</category></item><item><title>Excel dates counted differently and a reliable way of working out the day of the week</title><link>http://msmvps.com/blogs/robfarley/archive/2009/07/05/excel-dates-counted-differently-and-a-reliable-way-of-working-out-the-day-of-the-week.aspx</link><pubDate>Sun, 05 Jul 2009 11:11:28 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1698168</guid><dc:creator>Rob Farley</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1698168</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/07/05/excel-dates-counted-differently-and-a-reliable-way-of-working-out-the-day-of-the-week.aspx#comments</comments><description>&lt;p&gt;Following &lt;a href="http://msmvps.com/blogs/robfarley/archive/2009/07/01/40-000-days-since-the-beginning-of-time.aspx" target="_blank"&gt;my recent post about 40,000 days&lt;/a&gt;, I got a couple of emails telling me that Excel disagrees about when the 40,000th day is. And this is true – Excel counts Day 40000 as July 6th 2009, not July 7th.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom:0px;border-left:0px;margin:5px;display:inline;border-top:0px;border-right:0px;" title="" border="0" alt="" align="right" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/robfarley.metablogapi/8182.image_5F00_2220787A.png" width="424" height="213" /&gt;Unfortunately for Excel users, they’re wrong. And it’s down to the fact that Excel thinks that 1900 was a leap-year, when we all know it wasn’t. You see, leap-years only fall on the century year if the year is divisible by 400. So 2000 was a leap-year, but 1900 wasn’t, and 2100 won’t be either. &lt;/p&gt;  &lt;p&gt;What’s more, this has been a problem for ages, and it was a &lt;a href="http://support.microsoft.com/kb/214326" target="_blank"&gt;conscious decision to introduce the bug&lt;/a&gt;. Essentially, Lotus 1-2-3 thought 1900 was a leap-year, and to be consistent with the market leader of the day, Microsoft treated 1900 as a leap-year too. And nowadays, we have a situation where backwards compatibility is more important. Today, if you have an application which knows that day 40000 is July 7th, then you’d better not treat your date that same way in Excel (or vice-versa).&lt;/p&gt;  &lt;p&gt;The thing that I find really amazing with this is that Excel tells me that Feb 29, 1900 was a Wednesday. But it didn’t exist – so what happened that week? Actually (and you can check other calendars for this, including Windows’ one), Feb 28th was a Wednesday, and Excel gets the day of the week wrong for the first 59 days of its calendar.&lt;/p&gt;  &lt;p&gt;I know you don’t care, but perhaps you should – in case you ever write an application that needs to know what day of the week it is.&lt;/p&gt;  &lt;p&gt;Working out the day of the week is really trivial. For instance, in SQL Server, you can generally ask for the DATEPART(dw,…) of the date in question, and get a number back, telling you what day of the week it is. It’ll tell you 1 for the 1st day of the week, 2 for the 2nd, and so on.&lt;/p&gt;  &lt;p&gt;Which is great, until you find that someone in your organisation says that Sunday is the first of the week, but someone else insists that it’s Monday. In the movie industry, I think Thursday is the first day of the week. So then, when is the 5th day? In SQL we have @@DATEFIRST, which helps a lot, but a method I like to use is to count the number of days since a known Sunday (or whatever), and take the “mod 7”. If that’s zero, I’m an exact number of weeks since that known Sunday. It works nicely, and it’s simple enough for everyone to understand (and it works regardless of location or other changeable settings).&lt;/p&gt;  &lt;p&gt;But if you had picked your “known Sunday” in early 1900 using Excel, you’d’ve got it wrong, and your data might not work if you push your system out to SQL later (so pick something later – like 1901). I recently dealt with a date dimension that someone had put together in Excel and imported into SQL – if this data had gone back to 1900, then there would’ve certainly been errors in it (for a start, the import wouldn’t’ve worked because SQL would’ve complained that Feb 29, 1900 wasn’t a valid date).&lt;/p&gt;  &lt;p&gt;My preference with date dimensions is to use a lot of computed columns, and only ever populate a single field. It works nicely, and it’s almost no effort to extend the table to include extra dates when required.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1698168" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/excel/default.aspx">excel</category></item><item><title>40,000 days since the beginning of ‘time’</title><link>http://msmvps.com/blogs/robfarley/archive/2009/07/01/40-000-days-since-the-beginning-of-time.aspx</link><pubDate>Wed, 01 Jul 2009 00:12:33 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1697412</guid><dc:creator>Rob Farley</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1697412</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/07/01/40-000-days-since-the-beginning-of-time.aspx#comments</comments><description>&lt;p&gt;Next Tuesday feels like a significant day. Not only is it 7/7, and the fourth anniversary of the London bombings (in 2005), but it’s 40,000 days since the beginning of time. Well, not proper time, but since the start of the 1900s. &lt;/p&gt;  &lt;p&gt;SELECT DATEDIFF(day,&amp;#39;19000101&amp;#39;,&amp;#39;20090707&amp;#39;)+1 AS DaysOf1900s&lt;/p&gt;  &lt;p&gt;So if Day 1 is Jan 1, 1900 (as many systems tend to use – SQL actually considers it Day 0), Day 40000 is 7/7/2009.&lt;/p&gt;  &lt;p&gt;I actually rate the start of the twentieth century as a very significant event in the human race. In 1900 the world was changing faster than it had ever done before, and no-one can deny the significance of the twentieth century in history. I’m sure change will continue to become faster, but I found it interesting recently when I noticed that we were approaching this ‘milestone’ of sorts.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1697412" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/non-tech/default.aspx">non-tech</category></item><item><title>Access’ DISTINCTROW keyword explained – it means WHERE EXISTS</title><link>http://msmvps.com/blogs/robfarley/archive/2009/06/11/access-distinctrow-keyword-explained-it-means-where-exists.aspx</link><pubDate>Thu, 11 Jun 2009 11:25:15 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1694981</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1694981</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/06/11/access-distinctrow-keyword-explained-it-means-where-exists.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://www.convertu2.com" target="_blank"&gt;Steve Koop&lt;/a&gt; spoke recently at the &lt;a href="http://www.sqlserver.org.au" target="_blank"&gt;Adelaide SQL Server User Group&lt;/a&gt;, talking about things which don’t convert particularly nicely when upsizing from Microsoft Access to SQL Server 2008. I think this is a really important thing for SQL people to know, as there seem to be many Access databases living in even the largest organisations.&lt;/p&gt;  &lt;p&gt;One of the things he mentioned was DISTINCTROW. I’ve never really known what DISTINCTROW does, so I asked him. He sent me a link which explained the difference between DISTINCTROW and DISTINCT, and it described as “DISTINCTROW works on records, not just individual fields”. This might be good for some people, but I wanted to know a little more.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/aa140015.aspx" href="http://msdn.microsoft.com/en-us/library/aa140015.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa140015.aspx&lt;/a&gt; says “The DISTINCTROW keyword is similar to the DISTINCT keyword except that it is based on entire rows, not just individual fields.” – but it also goes on to say a little more, confirming my suspicions. “It is useful only when based on multiple tables, and only when you select fields from some, but not all, of the tables.”&lt;/p&gt;  &lt;p&gt;So DISTINCTROW is more about the JOIN type than anything else. It only applies if you are querying multiple tables, but not returning fields from all of them. So it’s a SEMI JOIN to the unused tables, which you write SQL Server using a WHERE EXISTS clause. It’s not really like DISTINCT at all – it’s about doing a Join without seeing the ‘duplication’ effect, clearly only feasible if you’re not returning columns from the other table.&lt;/p&gt;  &lt;p&gt;If you’re not sure what a Semi Join is, then just think about the WHERE EXISTS clause, and it should become clear. If you look at the execution plan of a query in SQL Server that uses WHERE EXISTS, you’ll see that it’s doing a Semi Join. And if you’re looking at queries which use DISTINCTROW, consider changing them to WHERE EXISTS instead.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1694981" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/adssug/default.aspx">adssug</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/access/default.aspx">access</category></item><item><title>Putting a Calculated Member into a Display Folder</title><link>http://msmvps.com/blogs/robfarley/archive/2009/06/09/putting-a-calculated-member-into-a-display-folder.aspx</link><pubDate>Tue, 09 Jun 2009 11:10:25 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1694718</guid><dc:creator>Rob Farley</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1694718</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/06/09/putting-a-calculated-member-into-a-display-folder.aspx#comments</comments><description>&lt;p&gt;There are some blog posts that are there to inform other people – this isn’t one of these. This is something I always seem to forget, and I’m hoping that writing it in here will cause me to never forget again. It’s the knot in my handkerchief, or the writing on my hand. &lt;/p&gt;  &lt;p&gt;I put an SSAS (2005) Calculated Member in a cube, and then have trouble trying to get it into a Display Folder, or associating it with a Measure Group…&lt;/p&gt;  &lt;p&gt;I always hit F4 and go hunting through the properties list… repeatedly pull down the drop down that says [Measures], looking for it… until I eventually remember the extra little button on the toolbar. The one in the picture on the right.&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/robfarley.metablogapi/2502.image_5F00_048E3486.png"&gt;&lt;img title="image" style="border-right:0px;border-top:0px;display:inline;margin-left:0px;border-left:0px;margin-right:0px;border-bottom:0px;" height="129" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/robfarley.metablogapi/6215.image_5F00_thumb_5F00_012C9CDE.png" width="244" align="right" border="0" /&gt;&lt;/a&gt; It’s the button between the Script button and the Check Syntax button… the button that always seems to escape out of my head, driving me crazy every few months.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1694718" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/ssas/default.aspx">ssas</category></item><item><title>Seriously cheap exams in Australia</title><link>http://msmvps.com/blogs/robfarley/archive/2009/05/06/seriously-cheap-exams-in-australia.aspx</link><pubDate>Wed, 06 May 2009 02:56:41 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1691922</guid><dc:creator>Rob Farley</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1691922</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/05/06/seriously-cheap-exams-in-australia.aspx#comments</comments><description>&lt;p&gt;If you’re an MCP in Australia and you haven’t passed any exams over the past couple of years (since July 1, 2007), then Microsoft has an offer at the moment to let you do an exam for only US$25 (until June 30, 2009). Ok, so that means the price really depends on the value of the Aussie dollar, but either way, it’s not a bad opportunity.&lt;/p&gt;  &lt;p&gt;The offer is only on for a very short time, but why not check out &lt;a title="http://www.learnandcertify.com/mcpupgrade/" href="http://www.learnandcertify.com/mcpupgrade/"&gt;http://www.learnandcertify.com/mcpupgrade/&lt;/a&gt; and see what you can do? I’m thinking it’s a nice opportunity to knock over one of those Upgrade exams to get yourself from MCITP:SQL2005 to MCITP:SQL2008. You don’t get a second shot with this one, and you can only get one voucher – but it’s so cheap you may as well try it.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1691922" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/australia/default.aspx">australia</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/certification/default.aspx">certification</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/professional+development/default.aspx">professional development</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+server+2008/default.aspx">sql server 2008</category></item><item><title>SQL Server 2008 SP1 download</title><link>http://msmvps.com/blogs/robfarley/archive/2009/04/08/sql-server-2008-sp1-download.aspx</link><pubDate>Wed, 08 Apr 2009 01:01:49 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1685733</guid><dc:creator>Rob Farley</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1685733</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/04/08/sql-server-2008-sp1-download.aspx#comments</comments><description>&lt;p&gt;You can get it from &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=66ab3dbb-bf3e-4f46-9559-ccc6a4f9dc19"&gt;http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=66ab3dbb-bf3e-4f46-9559-ccc6a4f9dc19&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;For all those people who have been waiting for SP1 before considering a migration to SQL Server 2008, it has now been released.&lt;/p&gt;  &lt;p&gt;There’s also a new version of the Feature Pack for SQL Server 2008, available from: &lt;a title="http://www.microsoft.com/downloads/details.aspx?familyid=B33D2C78-1059-4CE2-B80D-2343C099BCB4&amp;amp;displaylang=en" href="http://www.microsoft.com/downloads/details.aspx?familyid=B33D2C78-1059-4CE2-B80D-2343C099BCB4&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=B33D2C78-1059-4CE2-B80D-2343C099BCB4&amp;amp;displaylang=en&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1685733" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql+server+2008/default.aspx">sql server 2008</category></item><item><title>Time zone limbo</title><link>http://msmvps.com/blogs/robfarley/archive/2009/04/01/time-zone-limbo.aspx</link><pubDate>Wed, 01 Apr 2009 09:00:08 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1683678</guid><dc:creator>Rob Farley</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1683678</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/04/01/time-zone-limbo.aspx#comments</comments><description>&lt;p&gt;Australia is currently in an interesting week for time zones.&lt;/p&gt;  &lt;p&gt;Up until a couple of years ago, Daylight Savings finished on the last Sunday in March. That’s when the clocks got put back to Standard Time, as the Australian summer ended. Last year though, this got extended by a week, until the first Sunday in April. A similar change was made in October, changing the start of Daylight Savings from the last weekend of October to the first weekend of October. We now have six months of summer instead of five (although weather-wise, it’s a lot more…)&lt;/p&gt;  &lt;p&gt;That’s fine – most people have patched their machines happily, and don’t have a problem. My mobile phone is an old O2 XDA, running Windows Mobile 2003 (I once upgraded to a newer device, but a washing machine had an argument with it and won). Unfortunately, i don’t think there’s a patch for WM2003, and so this week my phone (and hence, my alarms) thinks that I’m an hour out.&lt;/p&gt;  &lt;p&gt;It’s fine when I’m in Melbourne or Sydney – I can set the time zone to be &lt;a href="http://en.wikipedia.org/wiki/Magadan" target="_blank"&gt;Magadan&lt;/a&gt; (which is in Russia), and the problem goes away. All good – I don’t really care where my phone thinks I am, just so long as the time is right.&lt;/p&gt;  &lt;p&gt;The problem is when I’m in Adelaide… Adelaide which is normally in GMT+0930 (yes, on the half-hour), but this week is still in GMT+1030. According to my mobile device, there is nowhere in the world that is GMT+1030 this week. So instead I’ve had to change my alarms to wake me up half an hour later, whilst I pretend I’m in Siberia. I recently learned that the Russian for “Bless You” (ie, that thing you say when someone sneezes) is “Bud Zdorov” (literally &amp;quot;Be Healthy”, and I apologise for the spelling. ‘Bud’ rhymes with ‘Good’). I’m not sure it’s quite enough to get me through though.&lt;/p&gt;  &lt;p&gt;One day I plan to visit Kathmandu, where the time zone is on the quarter-hour. Then I can return to the normality of Adelaide’s half-hour time zone.&lt;/p&gt;  &lt;p&gt;I’ve written about the &lt;a href="http://msmvps.com/blogs/robfarley/archive/2006/10/25/The-horror-of-daylight-savings-_2800_sorry-Perth_2900_.aspx" target="_blank"&gt;pain of daylight savings&lt;/a&gt; before, particularly around the pain of storing datetime fields in a database. Today i read &lt;a href="http://blogs.msdn.com/bartd/archive/2009/03/31/the-death-of-datetime.aspx" target="_blank"&gt;a post from Bart Duncan, recommending the use of datetimeoffset&lt;/a&gt;. I thoroughly agree with him, although I wonder how long it will be before people make this a priority.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1683678" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/australia/default.aspx">australia</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/adelaide/default.aspx">adelaide</category><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category></item><item><title>Converting to (and from) Julian Date (YYDDD) format in T-SQL</title><link>http://msmvps.com/blogs/robfarley/archive/2009/03/25/converting-to-and-from-julian-format-in-t-sql.aspx</link><pubDate>Wed, 25 Mar 2009 07:51:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1681165</guid><dc:creator>Rob Farley</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/robfarley/rsscomments.aspx?PostID=1681165</wfw:commentRss><comments>http://msmvps.com/blogs/robfarley/archive/2009/03/25/converting-to-and-from-julian-format-in-t-sql.aspx#comments</comments><description>&lt;p&gt;I often get asked how to convert a datetime into Julian Date format in T-SQL. People have differing opinions about what Julian means, but the one I got asked about most recently meant YYDDD, as often used by mainframe systems (I think this is Julian Date, as opposed to Julian Day which is the number of days since 4713BC). SQL Server doesn’t have a TO_JULIAN function, but we can make one easily enough.&lt;/p&gt;  &lt;p&gt;So we’re wanting to express a date as YYDDD, where YY is the two-digit form of the year, and DDD is the number of days since Dec 31st of the previous year (ie, the DDDth day of the year).&lt;/p&gt;  &lt;p&gt;Using the DATEPART function can get each part. YY for the year, and DY for the day of the year. I’m going to use @date as a variable here, of type datetime. Using the date type in SQL 2008 would work just the same.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;SELECT DATEPART(yy, @date), DATEPART(dy, @date)&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;However, to make sure that we have the year in two-digits only, we should convert this to a string and get the rightmost two characters. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;SELECT RIGHT(CAST(DATEPART(yy, @date) AS char(4)),2)&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We also need to pad the DDD with zeroes – which I’ll do by putting three zeroes in front of the number and getting the three rightmost characters.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;SELECT RIGHT(&amp;#39;000&amp;#39; + CAST(DATEPART(dy, @date) AS varchar(3)),3)&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Concatenating the YY and the DDD, we now have a TO_JULIAN function.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;CREATE FUNCTION dbo.to_julian(@date datetime) RETURNS char(5) AS        &lt;br /&gt;BEGIN         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; RETURN (SELECT RIGHT(CAST(YEAR(@date) AS CHAR(4)),2) + RIGHT(&amp;#39;000&amp;#39; + CAST(DATEPART(dy, @date) AS varchar(3)),3))         &lt;br /&gt;END&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Converting back again isn’t too hard – it’s just a matter of pulling the numbers out of the 5-character string. I’m going to assume we have a char(5) called @julian.&lt;/p&gt;  &lt;p&gt;We need to split the string up first.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;SELECT LEFT(@julian,2), RIGHT(@julian,3)&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The first bit becomes the year easily enough&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;SELECT CONVERT(datetime, LEFT(@julian,2) + &amp;#39;0101&amp;#39;, 112)&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The second half can be cast to a number, and then added back (subtracting one to get the maths right) using DATEADD.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;SELECT DATEADD(day, CAST(RIGHT(@julian,3) AS int) - 1, CONVERT(datetime, LEFT(@julian,2) + &amp;#39;0101&amp;#39;, 112))&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So now we have a FROM_JULIAN function:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;CREATE FUNCTION dbo.from_julian(@julian char(5)) RETURNS datetime AS        &lt;br /&gt;BEGIN         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; RETURN (SELECT DATEADD(day, CAST(RIGHT(@julian,3) AS int) - 1, CONVERT(datetime, LEFT(@julian,2) + &amp;#39;0101&amp;#39;, 112)))         &lt;br /&gt;END&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Easy stuff really, just a matter of thinking about what we mean by a particular format.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1681165" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/robfarley/archive/tags/sql/default.aspx">sql</category></item></channel></rss>