{"id":95,"date":"2009-10-05T20:38:00","date_gmt":"2009-10-05T20:38:00","guid":{"rendered":"\/lisa\/post\/2009\/10\/05\/Walkthrough-When-love-of-data-is-just-not-enough.aspx"},"modified":"2009-10-05T20:38:00","modified_gmt":"2009-10-05T20:38:00","slug":"walkthrough-when-love-of-data-is-not-enough","status":"publish","type":"post","link":"https:\/\/spacefold.com\/lisa\/2009\/10\/05\/walkthrough-when-love-of-data-is-not-enough\/","title":{"rendered":"Walkthrough: When love of data is not enough"},"content":{"rendered":"<p>\nNo matter how much we love to see our designed report brimming with data like a cornocopia, there are times when it&#39;s a little too much of a good thing.\n<\/p>\n<p>\n<a href=\"mailto:Fleming@CSGSolutions.com\" target=\"_blank\" title=\"Write to Linda for more details\" rel=\"noopener\">Linda<\/a> writes with the following question (using SQL 2005 and RDLs):\n<\/p>\n<blockquote>\n<p>\n\t1. I have a report that all parameters have a default so the report runs when it is opened before you click View Report. <\/p>\n<p>\t2. I don&#39;t want the report to run because it is pulling way too much data. I want the user to fill in one of the five parameters to limit the data (I don&#39;t care which one). <\/p>\n<p>\t3. I wrote custom code that checks to see if all parameters are nothing and returns a boolean. <\/p>\n<p>\t4. I use the Hidden property, with an expression that calls the custom code to either show a textbox saying &quot;Please fill in one parameter&quot; or the table that is the actual report. <\/p>\n<p>\t5. The problem is, that even when my table (actual report) is hidden (because they did not enter a parameter), the dataset is still running (and pulling way too much data). <\/p>\n<p>\t6. How can I get the dataset to NOT run unless they have entered one of the parameters. I have tried several things in my custom code but have not been successfull.\n\t<\/p>\n<\/blockquote>\n<p>\nWell, sure.&nbsp; Hiding a data region in the layout doesn&#39;t affect the data-loading. From the report&#39;s point of view, hiding a data region doesn&#39;t mean that some custom code or some other data region isn&#39;t using the data in this same dataset.&nbsp; You have to get &quot;back&quot;, closer to the data-pull, and further from the layout, to do this right.\n<\/p>\n<p>\nLinda was <strong>really<\/strong> close to getting this right without help, as you may be able to tell from the steps she&#39;s taken. She just needs a little boost. And this is a problem that besets us all &#8212; so I wanted to get it out there, in at least one version, as quickly as possible. (These days, &quot;as quickly as possible&quot; isn&#39;t as quickly as I&#39;d like&#8230; apologies to EVERYBODY who has been waiting in the queue.)\n<\/p>\n<p>\nThere are a lot of&nbsp;ways to do this.&nbsp; Some involve dynamic sql for the actual report query, and&nbsp;some don&#39;t.&nbsp; I&#39;m going to show&nbsp;some basic ingredients for the ones that don&#39;t need a dynamic query, which are surprisingly simple.\n<\/p>\n<h3>1. Setup: Not important<\/h3>\n<p>\nFor this walkthrough I&#39;ll use a very boring table with very boring data.&nbsp;\n<\/p>\n<p>\nThe table lists event notices that are triggered in&nbsp;a system.\n<\/p>\n<p>\nIt doesn&#39;t matter what&#39;s in it; all you have to know, really, is that the Designer preview in VS 2008 throws an &quot;Out of Memory&quot; exception if I run the report with no filters.\n<\/p>\n<h3>2. Consider the needs of each individual parameter<\/h3>\n<p>\nIn this walkthrough I&#39;ve used&nbsp;&quot;start&quot; and &quot;end&quot;&nbsp;dates&nbsp;for one filter, and a picklist of event notice types&nbsp;for another one.&nbsp; These are just a couple of common filter types.\n<\/p>\n<p>\nBut these two params&nbsp;won&#39;t fit every case and every data set.&nbsp; You need to look at each parameter in <strong>your<\/strong> report, and decide how to apply what I&#39;m doing in the example.\n<\/p>\n<h3>3. To dream the impossible dream<\/h3>\n<p>\nThe picklist parameter&nbsp;gets its available valules from a second data set.&nbsp; The entries come mostly from a lookup table, but I&#39;ve added a UNION statement, like this:\n<\/p>\n<p><font color=\"#0000ff\">SELECT<\/font> Notice_Type<font color=\"#808080\">,<\/font>2 <font color=\"#0000ff\">AS<\/font> Ord <font color=\"#0000ff\">FROM<\/font> S2S_NoticeTypes <br \/>\n<font color=\"#0000ff\">UNION<\/font> <br \/>\nSELECT <font color=\"#ff0000\">&#39;Please select&#39;<\/font> <font color=\"#0000ff\">AS<\/font> Notice_Type<font color=\"#808080\">,<\/font> 1 <font color=\"#0000ff\">AS<\/font> Ord <font color=\"#0000ff\"><br \/>\nORDER BY Ord<font color=\"#808080\">,<\/font> Notice_Type <\/font><\/p>\n<p>\nFor the picklist&#39;s default value, &nbsp;I&quot;ve set the value &#39;Please select&#39;.&nbsp;\n<\/p>\n<p>\nSo far, I&#39;ve set a &quot;known impossible&quot; value as the default value.&nbsp; I now use this &quot;impossible&quot; default value in the actual SQL query, like this:\n<\/p>\n<p>\n<font color=\"#0000ff\">SELECT<\/font> <font color=\"#808080\">*<\/font> <font color=\"#0000ff\">FROM<\/font> S2S_Notices <font color=\"#0000ff\"><br \/>\nWHERE<\/font> <br \/>\n&nbsp;&nbsp;&nbsp; Notice_Requested <font color=\"#808080\">&gt;<\/font> @NoticeRequestedAfter <font color=\"#808080\">AND<\/font> <br \/>\n&nbsp;&nbsp;&nbsp; Notice_Requested <font color=\"#808080\">&lt;<\/font> @NoticeRequestedUntil <font color=\"#808080\">AND<\/font> <br \/>\n&nbsp;&nbsp;&nbsp; <span style=\"background-color: #ffff99\"><font color=\"#808080\">(<\/font>@NoticeType <font color=\"#808080\">=<\/font> <font color=\"#ff0000\">&#39;Please select&#39;<\/font> <font color=\"#808080\">OR<\/font> Notice_Type <font color=\"#808080\">=<\/font> @NoticeType<font color=\"#808080\">)<\/font> <\/span>\n<\/p>\n<p>\nNotice the all-important parens.&nbsp;This is a simple trick, but one I use a lot, to say&nbsp;&quot;evaluate this parameter only if it&nbsp;has a real value&quot;.&nbsp;\n<\/p>\n<p>\nMeanwhile, you can see that the date parameters in the query <strong>are<\/strong> always evaluated. What gives?\n<\/p>\n<p>\nThe&nbsp; date&nbsp;parameter defaults are&nbsp;set a little differently:\n<\/p>\n<p class=\"code\">\n=DateAdd(<font color=\"#a31515\">&quot;d&quot;<\/font>,1,Today())\n<\/p>\n<p class=\"code\">\n=DateAdd(<font color=\"#a31515\">&quot;d&quot;<\/font>,2,Today())\n<\/p>\n<p>\nThese are still &quot;impossible&quot; defaults for this particular table, because I know for sure the event notice queue has no future dates in it.&nbsp;&nbsp;\n<\/p>\n<p>\nLook: Dates are particularly tricky as parameters in Reporting Services, especially when created as empties.&nbsp; I don&#39;t even know if Linda has any dates&nbsp;in her parameter set, but I wanted to use at least one example.&nbsp; She <strong>may<\/strong>&nbsp; be using nulls or empties for date defaults, and we could easily handle this on the SQL end if necessary; it&#39;s on the RS end that it&#39;s tricky.&nbsp; Read on. I think you&#39;ll see how it will work.\n<\/p>\n<p class=\"NB\">\nYou notice I used Today() instead of Now() above? I didn&#39;t want times in this case, you might in yours.&nbsp; There are a ton of other silly date hang-ups.\n<\/p>\n<h4 class=\"NB\">4. Pick your defaults wisely!<\/h4>\n<p>\nMaybe in&nbsp;Linda&#39;s case,&nbsp;a different strategy than &quot;impossible&quot; defaults shown to the user&nbsp;would be better. &nbsp;\n<\/p>\n<p>\nFor example, it sounds to me like she&#39;s using explicit nulls as defaults in at least one parameter&#39;s case, as an indication that this parameter is optional.&nbsp;\n<\/p>\n<p>\nShe can use default nulls, if she wants, for all the parameters!&nbsp; Or, she can&nbsp;mix and match with &quot;Select a value&quot; style defaults for some, and null defaults for others.\n<\/p>\n<p>\n<strong>When all defaults are provided but all parameters are actually optional<\/strong>,&nbsp;as in Linda&#39;s case, I usually end up with a query that has a particularly weird-looking&nbsp;WHERE clause.&nbsp; Let&#39;s adapt my example to show exactly this case.\n<\/p>\n<p>\nNotice the first part of the WHERE clause here, which will come into play if none of the parameters are&nbsp; chosen:\n<\/p>\n<p class=\"code\">\n<font color=\"#0000ff\">SELECT<\/font> <font color=\"#808080\">*<\/font> <font color=\"#0000ff\">FROM<\/font> S2S_Notices <font color=\"#0000ff\"><br \/>\nWHERE<\/font>&nbsp;<br \/>\n<font color=\"#808080\">(<\/font>@NoticeRequestedAfter <font color=\"#808080\">IS<\/font> <font color=\"#808080\">NULL<\/font> <font color=\"#808080\">AND<\/font> <br \/>\n&nbsp;@NoticeRequestedUntil <font color=\"#808080\">IS<\/font> <font color=\"#808080\">NULL <\/font><font color=\"#808080\">AND<\/font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#008000\">&#8212; just add one &quot;impossible&quot; condition&nbsp;<\/font><br \/>\n&nbsp;@NoticeType <font color=\"#808080\">IS<\/font> <font color=\"#808080\">NULL<\/font> <span style=\"background-color: #ffff99\"><font color=\"#808080\">AND<\/font> Notice_Type <font color=\"#808080\">=<\/font> <font color=\"#ff0000\">&#39;XXXX&#39; <\/font><\/span>&nbsp;&#8212; <font color=\"#008000\">at the end of the all-null params<br \/>\n<font color=\"#808080\">)<\/font><\/font><font color=\"#000000\">&nbsp;<\/font><br \/>\n<font color=\"#808080\">&nbsp; <strong>OR<\/strong><\/font><strong>&nbsp;<\/strong><font color=\"#008000\"> &#8212;&nbsp;your real WHERE clause is here, whatever it happens to be:<\/font><br \/>\n<font color=\"#808080\">( ( <font color=\"#000000\">@NoticeRequestedAfter<\/font> IS NULL OR <\/font>Notice_Requested <font color=\"#808080\">&gt;<\/font> @NoticeRequestedAfter) <font color=\"#808080\">AND<\/font>&nbsp;<br \/>\n&nbsp;&nbsp;<font color=\"#808080\">(&nbsp;<font color=\"#000000\">@NoticeRequestedUntil<\/font> IS NULL OR<\/font> Notice_Requested <font color=\"#808080\">&lt;<\/font> @NoticeRequestedUntil)&nbsp;&nbsp; <font color=\"#808080\">AND<\/font>&nbsp;<br \/>\n&nbsp;&nbsp;<font color=\"#808080\">( <\/font>@NoticeType <font color=\"#808080\">=<\/font> <font color=\"#ff0000\">&#39;Please select&#39;<\/font> <font color=\"#808080\">OR<\/font> Notice_Type <font color=\"#808080\">=<\/font> @NoticeType<font color=\"#808080\">)<\/font> <br \/>\n<font color=\"#808080\">)<\/font>\n<\/p>\n<p class=\"NB\">\nUpdate (10\/7\/2009) after talking with Linda:<\/p>\n<p>The above query, written in haste with the second part (after the OR) copied verbatim from the earlier example, is probably <strong>really<\/strong> confusing, and I&#39;m sorry about that.<\/p>\n<p>The second part doesn&#39;t match the first part (on the top half we&#39;re using a null test for @NoticeType, and on the bottom half we&#39;re testing for &#39;Please select&#39;, same way we did it in the earlier example.<\/p>\n<p>What&#39;s more, I left out an all-important test on the second part, to ensure that at least one parameter had been edited by the user. <\/p>\n<p>A more appropriate example would look something like this:\n<\/p>\n<p class=\"code\">\n<font color=\"#0000ff\">&nbsp;&nbsp; SELECT<\/font> <font color=\"#808080\">*<\/font> <font color=\"#0000ff\">FROM<\/font> S2S_Notices <font color=\"#0000ff\"><br \/>\n&nbsp;&nbsp; WHERE<\/font>&nbsp;<br \/>\n<font color=\"#808080\">&nbsp;&nbsp; (<\/font>@NoticeRequestedAfter <font color=\"#808080\">IS<\/font> <font color=\"#808080\">NULL<\/font> <font color=\"#808080\">AND<\/font> <br \/>\n&nbsp;&nbsp; &nbsp;@NoticeRequestedUntil <font color=\"#808080\">IS<\/font> <font color=\"#808080\">NULL <\/font><font color=\"#808080\">AND<\/font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color=\"#008000\">&#8212; just add one &quot;impossible&quot; condition&nbsp;<\/font><br \/>\n&nbsp;&nbsp; &nbsp;@NoticeType <font color=\"#808080\">IS<\/font> <font color=\"#808080\">NULL<\/font> <span style=\"background-color: #ffff99\"><font color=\"#808080\">AND<\/font> Notice_Type <font color=\"#808080\">=<\/font> <font color=\"#ff0000\">&#39;XXXX&#39; <\/font><\/span>&nbsp;&#8212; <font color=\"#008000\">at the end of the all-null params<br \/>\n<font color=\"#808080\">&nbsp;&nbsp; )<\/font><\/font><font color=\"#000000\">&nbsp;<\/font><br \/>\n<font color=\"#808080\">&nbsp;&nbsp; &nbsp; <strong>OR<\/strong><\/font><strong>&nbsp;<\/strong><font color=\"#008000\"> &#8212;&nbsp;your real WHERE clause is here, whatever it happens to be:<\/font><br \/>\n<font color=\"#808080\">&nbsp;&nbsp; ( <span style=\"background-color: #ffff99\">(<font color=\"#000000\">@NoticeRequestedAfter<\/font> IS NOT NULL&nbsp;<font color=\"#000000\">&nbsp;<\/font><font color=\"#808080\">OR&nbsp;<br \/>\n<font style=\"background-color: #ffffff\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/font> <font color=\"#000000\">@NoticeRequestedUntil<\/font> IS NOT NULL&nbsp; OR&nbsp;&nbsp;<br \/>\n<font style=\"background-color: #ffffff\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/font> <font color=\"#000000\">@NoticeType <\/font><font color=\"#808080\">IS<font color=\"#000000\"> <\/font><font color=\"#808080\">NOT NULL&nbsp; <font color=\"#000000\"><font color=\"#808080\">)<\/font> <\/font><font color=\"#808080\">AND<\/font><font color=\"#000000\">&nbsp;<\/font><\/font><\/font><\/font><\/span><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp; ( <font color=\"#000000\">@NoticeRequestedAfter<\/font> IS NULL OR <\/font>Notice_Requested <font color=\"#808080\">&gt;<\/font> @NoticeRequestedAfter<font color=\"#808080\">)<\/font> <font color=\"#808080\">AND<\/font>&nbsp;<br \/>\n&nbsp;&nbsp; &nbsp;&nbsp;<font color=\"#808080\">(&nbsp;<font color=\"#000000\">@NoticeRequestedUntil<\/font> IS NULL OR<\/font> Notice_Requested <font color=\"#808080\">&lt;<\/font> @NoticeRequestedUntil<font color=\"#808080\">)<\/font>&nbsp; <font color=\"#808080\">AND<\/font>&nbsp;<br \/>\n&nbsp;&nbsp; &nbsp;&nbsp;<font color=\"#808080\">( <\/font>@NoticeType <font color=\"#808080\"><font style=\"background-color: #ffff99\">IS<font color=\"#808080\"> NULL<\/font><\/font><font color=\"#000000\" style=\"background-color: #ffffff\"> <\/font><\/font><font color=\"#808080\">OR<\/font> Notice_Type <font color=\"#808080\">=<\/font> @NoticeType<font color=\"#808080\">)<\/font> <br \/>\n<font color=\"#808080\">&nbsp;&nbsp; )<\/font>\n<\/p>\n<p class=\"NB\">\n&#8230; or the two <strong>@NoticeType <\/strong><font color=\"#808080\"><strong>IS NULL<\/strong>&nbsp;<\/font> clauses above could both be changed to&nbsp;<font color=\"#808080\"> <\/font><strong>@NoticeType <font color=\"#808080\">=<\/font> <font color=\"#ff0000\">&#39;Please select&#39;<\/font><\/strong>, instead.&nbsp;\n<\/p>\n<h3>5. &nbsp;&nbsp;Can it be easier?<\/h3>\n<p>\nOh, definitely.\n<\/p>\n<p>\nThere&#39;s a good chance&nbsp;Linda will just take the ball up and run with it if this is enough to get her started.&nbsp; &nbsp;&nbsp;\n<\/p>\n<p>\nShe&#39;s probably also see that she can make her life a whole lot easier if she passes this stuff to a sproc. Then she can basically say SELECT TOP (@TopN) &nbsp;PERCENT where she evaluates @TopN to be 0 in certain conditions and 100 in others.&nbsp;\n<\/p>\n<p class=\"NB\">\nYou do remember that <a href=\"\/lisa\/2007\/11\/17\/One-more-for-the-road-Labels-Times-N-for-SQL-Server-and-VFP\/\" target=\"_blank\" title=\"blog post about neat syntax you can use here\" rel=\"noopener\">MS SQL 2005 and above have variable Top (N) syntax<\/a>, right? It works with the Percent keyword.\n<\/p>\n<h3>6. The &quot;reveal&quot;<\/h3>\n<p>\nSo, now comes the fun part: showing this in the RDL itself.&nbsp; Instead of Linda&#39;s conditionally-hidden textbox, I decided to use a textbox with this expression:\n<\/p>\n<p class=\"code\">\n=IIF(CountRows(<font color=\"#a31515\">&quot;dsMain&quot;<\/font>)= 0, <br \/>\n<font color=\"#a31515\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;Please edit the filter values to return data&quot;<\/font>,<br \/>\n<font color=\"#a31515\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;You have selected &quot;<\/font> &amp; CountRows(<font color=\"#a31515\">&quot;dsMain&quot;<\/font>).ToString()<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;)&nbsp;&nbsp;&amp; <font color=\"#a31515\">&quot; rows.&quot;<\/font>\n<\/p>\n<p>\n&#8230; no particular reason, I just thought it would look nice. Of course the &quot;false&quot; part of the IIF could have been an empty string, too.&nbsp;&nbsp; In Linda&#39;s case, if she&#39;s using nulls for defaults, she might want to say &quot;Please edit at least one filter value&quot; or something like that.\n<\/p>\n<p>\nI could also have chosen to use the NoRowsMessage property of the Table layout control, either instead of or alongside&nbsp;the specialized message textbox.&nbsp;&nbsp;This property is&nbsp;pretty convenient (I think all the data region controls have it), although not as flexible in the formatting department.\n<\/p>\n<h3>7. Take your bows<\/h3>\n<p>\nObviously, if I&#39;m talking about using NoRowsMessage property of the Table layout control, I didn&#39;t choose to hide the table when there wasn&#39;t any data.&nbsp;&nbsp;I thought the headers looked nice.\n<\/p>\n<p>\nYou can definitely&nbsp;hide the table&nbsp;if you want to &#8212; whether on the basis of the parameters values or CountRows(&quot;dataset scope&quot;) is up to you.&nbsp;Just remember that there may be times that the parameters are edited by the user but CountRows() is still 0.&nbsp; Do you want to show the table, or not?\n<\/p>\n<p>\nAnd also remember that, as Linda found,&nbsp;hiding something in&nbsp;the layout is&nbsp;just not the end of the story if you&#39;re looking to optimize the report.\n<\/p>\n<p>\n<em>This&nbsp;<\/em>&nbsp;is the end of the story. Or at least the end of my walkthrough.&nbsp; It&#39;s a bit rushed (Linda&#39;s apparently on a deadline), so I might have missed something important or not been explicit enough somewhere.\n<\/p>\n<p>\nThat&#39;s okay. In my experience, you guys know how to find me &lt;g&gt;.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No matter how much we love to see our designed report brimming with data like a cornocopia, there are times when it&#39;s a little too much of a good thing. Linda writes with the following question (using SQL 2005 and RDLs): 1. I have a report that all parameters have a default so the report<a class=\"more-link\" href=\"https:\/\/spacefold.com\/lisa\/2009\/10\/05\/walkthrough-when-love-of-data-is-not-enough\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,6],"tags":[],"class_list":["post-95","post","type-post","status-publish","format-standard","hentry","category-reporting","category-sql-server"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/95","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/comments?post=95"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/95\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/media?parent=95"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/categories?post=95"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/tags?post=95"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}