Look at that, it’s T-SQL Tuesday #42, how can I miss that?!

This month’s party is hosted by Wendy Pastrick and the topic is about change in the work life, possibly related to technology.  Well yeah, in my career of approximately fifteen years now I can write a couple of words on that subject.  Here’s the story of my career.

Introduction

For those who don’t know me yet I have something to confess: I used to be a software developer!  And I’m not ashamed to admit this.  Perhaps not that surprising, fifteen years ago you didn’t finish your studies to conclude: "And now I’m going to be a Business Intelligence consultant!".  Oh no, not at all.

During my studies, out of all possibilities, I already knew what I liked most: to develop software.  And I also quickly learned that my favorite language would not be COBOL, too outdated.  It wouldn’t be Visual Basic either, feels like you’re writing a book.  I prefer the shorter C/C++ syntax style.  I also knew that I didn’t want a consultancy position.  I considered a consultant to be an expert, and how could I be an expert after just having finished my studies??

Change 1.1

The first three years of my career I was an in-house C++ programmer.  Then I got involved with a software package that was written in VB6.  They were lacking manpower to implement new functionality and I was asked to help out.  So I did some programming in VB6 because there was no other option.

Then the first version of .NET arrived and guess what I did?  Part of the package’s functionality was the import of data out of flat files.  My job was to automate this process.  SSIS would have been perfect for the job but that didn’t exist yet.  I did use DTS for a couple of things, but not here.  The existing code consisted of about 15,000 lines of VB6 code which means redesigning was not an option anyway.  So I wrote a Windows service in C# that called the VB6 code!  Process automated!

Change 1.2

I’d also been using C# to write a couple of tools to help me in my day-to-day job.  Then the opportunity arose to be part of a new project which would be written completely in C#.  I was happy to be part of this!  Compared with VB6 and VC++6, the new Visual Studio for .NET was really a joy to work with!

Change 1.3

After a good year or so, upper management decided to go on the free tour: instead of .NET we were required to use Java for any new development projects.  Sure, why not give that a try then?!  One of the subprojects on which I worked was an activity monitoring tool for our server application.  I ended up developing some stored procedures to extract statistics out of logging tables.  At that time I wasn’t familiar with the ETL acronym yet, but that’s what I was doing.  Nowadays I would use SSIS for such a task.  There was also a reporting part to the project so I coded a website, in Java, to display those numbers, with drill through functionality and all that fancy stuff.  Nowadays I would definitely use SSRS!

Several months and lots of code later I realized that I didn’t enjoy Java (and all involved tools, libraries, …) as much as I enjoyed C#.  Sure, I could get stuff done.  But it wasn’t always as straightforward as I would have hoped, and online info was not as good – in my opinion.

After ten years of being an in-house developer at three different companies, I decided the time had come for a bigger change!  What I haven’t mentioned so far is that practically all projects in which I was involved used SQL Server as database engine.  And I always enjoyed playing around with that.

Change 2.0

In my new job I would no longer be an in-house employee and my main activity wouldn’t be writing code: I became a SQL Server Business Intelligence Consultant!

My employer, Ordina, gave me some time to cope with the change.  I was allowed to spend some weeks studying books and even going for a week of training (SSAS).

I was also encouraged to start blogging.  Initially it was a challenge to find topics to blog about.  But only initially, nowadays I’ve got too many topics and not enough time.  I discovered it was actually interesting to write about things I’d encountered for real.

Here’s such an example.  In one of my shorter project interventions, I ended up calling a web service through SQL CLR.  This was not an easy task.  Without my developer background I would probably never have succeeded here!  When I turned this into an article on my blog it became my first real hit!  The article, Calling a Web Service From SQL Server 2005, was posted Nov 11, 2008 and has gotten over 26,000 page views to date.  Even today it is still one of the more popular pages I’m hosting.

Besides teaching others through my blog I also discovered that forums can be a really interesting way to improve skills.  So in August 2008 I created a free account at Experts Exchange.  I also found out that helping out on forums combined with blogging is a real win-win situation: it helps me to find topics to write about and I can help people out by referring to an already-written article!

In February 2012 I was delighted to read that EE had found my forum activity worth an extra credit so I was given the MVE – Most Valuable Expert – award! Since then I have managed to reach the number one position in the SSRS zone with over one million points in total and it looks like I’ll be staying there for some time.

Lately I have started presenting.  So far I have found that to be a stressing yet rewarding experience.  My next presentation will be at the Community Day where both I and my colleague Koen Verbeeck will each talk for about half an hour about SSRS visualizations.  The target audience are mainly developers, that’s going to be interesting!  And it will be my first time on a stage in a cinema room, fearing the spotlights already!

Ow, and registration is open so see you there?  Come over to say hello if you are planning to attend the conference.  We are scheduled in the first slot so once that’s over I’ll be relieved of my stress!

Conclusion

Did a change in technology influence my career path?  Ow yeah, I do believe it did!  SQL Server was not the only tech that influenced it but I do consider it the most significant one.  And I’m glad it did too, keeps things challenging! 

Now I’m off to install Oracle.  So long, and thanks for all the fish!

PS: one of my statements in this post is a lie.

Valentino.

Share

Tags: ,

The other day I needed to be able to study the SQL Server 2012 documentation, aka Books Online or BOL, to prepare for an exam while sitting on the train. So I was looking for the latest BOL download but that search wasn’t very successful. It took me a while to realize that what I was doing was no longer valid! Microsoft is no longer distributing the Books Online through the Downloads site!

Well, not entirely true, read on for details.

Because it took me some time to realize what was going on I decided to write a quick post on how to make the BOL 2012 available locally. Basically you’ve got two options.  Let’s start with the first one.

Method 1: Help Library Manager

The first – newly-introduced in SQL Server 2012 – method uses something called Help Library Manager.

This is a generic Microsoft product documentation management system, not exclusively for SQL Server.

Here are the steps to follow to get the SQL Server 2012 docs installed locally.  This method assumes that you’ve already got SQL Server 2012 installed and that your PC is connected to the internet.

To start, click the Manage Help Settings link located in the Documentation & Community subgroup of your SQL Server 2012 start menu shortcut group.

Manage Help Settings

This will open up the Help Library Manager mentioned earlier:

Help Library Manager: installing online content

Click the Install content from online link.  The Help Library Manager starts by fetching the list of available books.  Once finished, locate the SQL Server 2012 content:

Installing the SQL Server 2012 books

Click the Add link next to any book you’d like to install locally.  The link will change to Cancel as shown in following screenshot:

Selecting the books to be installed locally

When you’ve selected all books you’re interested in, click the Update button.  The Library Manager will now start downloading all the content you’ve requested.

Help Library Manager is downloading the requested packages

Now go and get a coffee.  When you’re back, you should be able to click the Finish button and the Books Online will be available locally:

SQL Server 2012 Books Online ready to be used

Method 2: Download from Download Center

It turns out Microsoft took into account that not all computers are able to access the internet, which is a requirement for method 1.  Microsoft does still have something available for download through the Download Center.  However, when I came across the link I hadn’t realized that this was actually the BOL download.  The reason that I didn’t realize this was because the stand-alone BOL download is now called Product Documentation for Microsoft SQL Server 2012 for firewall and proxy restricted environments. I thought this was documentation regarding firewall and other network-related issues but this is actually the full Books Online download!

So if you’re interested in the old-skool BOL download, check this out: [Download Center] Product Documentation for Microsoft SQL Server 2012 for firewall and proxy restricted environments

Have fun!

Valentino.

References
Add or Remove Product Documentation for SQL Server

Share

Tags: , ,

Fruit Basket (ref. http://ciaopaolo.com/store/category/fruit-gift-baskets/)If you’re reading this, you’re probably already aware that SQL Server Reporting Services has got some useful collections that can be used in expressions all over the report?  Well, just in case you’re not, I’ll cover not just the hidden ones but all of them.

Collections, huh?

If you’ve got some programming experience then I’m sure this concept is familiar to you.  On the other hand, and in that case you’re new to all this, think of a collection as a, well… a gathering of objects.  Similar to a fruit basket which is a collection of fruit.

Let’s first have a look at the syntax, how can these collections be used?

I’m using SSRS 2012 SP1 but this concept is not new.  I believe all expression will even work in SSRS 2005.

Collection Syntax

Each item in a collection can be referenced through two different methods, both giving the same result.  Let’s continue the fruit basket example.  If SSRS had a collection called FruitCollection, you’d be able to reference the different fruits in that basket through following syntax:

FruitCollection!FruitName

For instance FruitCollection!Lemon will give you the Lemon object, assuming such an object exists in the collection.  That’s the first method.  The advantage of this method is that the expression builder will display a nice popup list of all the items in the collection once you’ve typed the exclamation mark.

The second method of referencing an item in the collection is by using the following Visual Basic syntax:

FruitCollection("Lemon")

This syntax requires you to pass the object name as a string.  As a result of that, you don’t get any syntax checks on the object name, so if you’d typed Limon you would only notice the problem when you actually run the report and get an error.  That’s why I prefer using the syntax with the exclamation mark so that’s the syntax I will be using for the examples further down in this article.

Each object in a collection also has a number of properties that can be consulted.  To continue the fruit basket example, the Lemon object could have a Color property.  To access that property you would use this expression:

FruitCollection!Lemon.Color

Alright, time to have a closer look at the different collections in SSRS!

The Parameters Collection

If you’ve got any experience implementing report parameters, I’m sure you already know this one.  The Parameters collection allows you to access your report parameters.

In case you’re dealing with a multiple-valued parameter, there are a couple of interesting properties you should be aware of, such as the Count and IsMultiValue property.  Careful though: the Count property returns the number of selected values, not the number of available values!

To reference just one of the selected values you can use the following syntax:

Parameters!YourParameter.Value(0)

This expression will return the Value property of the first item in the selected items list.  Note that it’s a zero-based index.

Another interesting function you should be aware of is the Join.  It allows you to join the different selected values together into one string.

The screenshot below shows you some expressions and their result.  The Category parameter has got three available values with two of them selected.

The Parameters Collection

The Variables Collection

The Variables collection gives you access to the report variables.  To demonstrate this, I’ve set up the following variable:

Report Variables

And here’s the expression to access its value:

Variables!MyVariable.Value

 

The Globals and User Collections

The Globals and User collections contain some useful properties and are provided by default in every report.  These are the items available through the Built-in Fields category in the expression builder:

The Built-in Fields: objects in Globals and User collection

Through those collections you’ve got access to some really interesting properties, such as the RenderFormat.Name property which indicates what output format is being rendered.  I’ve actually mentioned this one before: Hide/Show Items Dependant On Export Format (SSRS)

Okay, time to get started with those hidden collections.  But first, why do I call them hidden?  Simple, because they are not shown in the expression builder Category list, as you can see from the previous screenshot.

The (Hidden) ReportItems Collection

A very commonly used collection is the one called ReportItems.  It allows you to reference the different textboxes on your report.  If you know that each “cell” in a Tablix is actually a Textbox, well, I’m sure you realize that this can be quite useful in certain situations.

Let’s have a look at a basic example.  Say I want to retrieve the list of selected Category values that’s shown in the screenshot in the Parameters Collection subchapter above.

Tip: always give your textbox a clear name when you’re going to reference it in an expression.  Never use the default Textbox666 name.  You can rename a textbox by changing its Name property.

In the following expression you can see that I’ve given the textbox another name, one that indicates what it contains:

ReportItems!txtFilterValues.Value

And here’s the result of that expression:

Using the ReportItems collection

Tip: the above is only possible if the textboxes are not in a group in the tablix.  So the tablix on the left does not contain any grouping, it’s a simple table with five basic rows and two columns.

The (Hidden) DataSources and DataSets Collections

Finally we’ve come to the collections which made me write this article.  Did you know it’s possible to display your dataset query in your report?  That’s right, through the DataSets collection you can access your actual query string!  And through the DataSources collection you have access to some other properties, such as the source type and the shared data source being referenced.

My report has got the following data sources and datasets defined:

Data Sources and Datasets

As indicated by the arrow in the data source icon, AdventureWorksDW2012 is referencing a shared data source while tempdb_embedded is an embedded source in the report.

Here are some examples of possible expressions and their result:

Using the DataSources and DataSets collections

Through the DataSources collection you have access to a Type property on the source.  This property is only given a value in case of an embedded data source.

You also have access to a property called DataSourceReference.  It contains the name of the shared data source being referenced so only contains a value in case of a shared data source.

And through the DataSets collection you can access the CommandText property, which returns your actual query statement.  This can be particularly useful when you’re building your query dynamically through an expression, very interesting for troubleshooting!

There’s also a property called RewrittenCommandText.  When I initially saw that property I thought it would return the statement with any parameters replaced with their actual values.  Well, I was wrong, as the screenshot above indicates.  Apparently this property is used for model-based queries, as mentioned by Robert Bruckner.  I try to avoid report models…

Conclusion

This article introduced the concept of collections in Reporting Services and then went into explaining the use of each of them, including a couple of hidden collections.

Have fun!

Valentino.

References

Built-in Collections in Expressions (Report Builder and SSRS)

What DataSet Query Text Is Executed?

Share

Tags: ,

Ever since I started using @ValentinoV on Twitter a bit more actively, which is now more than a year ago, I have also been exploring different methods of announcing my new blog posts to the world.  One of the methods I use is sending out a couple of tweets to my followers.  So far I had been adding the prefix [Blog] as a standardized way of working and I also add relevant hashtags, such as #SSRS when the post is about Reporting Services.

Here’s an example:

Tweet using the [Blog] prefix

Then Jamie Thomson, aka SSIS Junkie, made me aware of a blog post he had posted earlier this week.

The power of Twitter: being able to quickly contact someone without the need of email

And in that post, he introduced an interesting alternative to what I (and a lot of other SQL Server bloggers) was doing!  Instead of using that [Blog] prefix it’s better to use a hashtag!  Why is that better?  Well, because searches and filters on hashtags work better than searches on just plain text. In fact, he proposes several hashtags.  Have a look at his post for the details: Bootstrapping SQL Server bloggers and blog readers with Twitter!

And here’s my earlier tweet reworked as per Jamie’s proposed standards:

Tweet using Jamie Thomson standards

However, the #blogged hashtag is not the one I will be using.  Several other bloggers commented on his post that they’re more in favor of the concatenation of #blogged and #sqlserver into #sqlblog.  I like that proposal because it’s closer to my earlier prefix and it uses less characters.  Given the nature of Twitter, if we can deliver the same message using less characters then that would be the preferred method, right? So that’s the one I will be using from now on!

I’ll even demonstrate it by updating this post once I’ve tweeted about it.  Yeah, a recursive blog post!

Tweet to demonstrate usage of the adapted standard

Have fun, and spread the word!

Valentino.

Share

Tags: ,

Unfiltered Coffee - http://www.flickr.com/photos/derektor/92480692/In this article I’ll be describing a method which you can use to filter data in your Reporting Services reports without making any changes to the dataset query.

To get started, I’ll first imagine I’m being interviewed.  (Yeah, I like that.)

Q: You mentioned “without making any changes to the dataset query”.  So you’ll be filtering on the SSRS side then?

A: (Darn, I think she’s onto me.)  Well, yes.

Q: Would you recommend this method?

A: (Yep, she is.) Well, erm, no.  For performance reasons it’s much better to filter on the database server side.  You don’t waste any network bandwidth and database servers are specialized in filtering data.

Q: Then why are you writing an article about filtering on the report side?

A: Well, because sometimes you don’t have another option.  Not all data sources are as flexible as SQL Server, and SSRS supports many different providers.  In some occasions, the DBA that supports exotic data source X gives you a command, similar to a stored procedure call, that returns the data for your report.  And you don’t get any say on how that gets implemented, you’re just told to use that command.  Unfortunately that command returns items A-Z while the report has an item filter.  In those scenarios, it’s interesting if you’d be able to filter on the report side.

Q: Let’s say I would like to filter on the database server side, how would I do that?

A: Just use the WHERE clause in your query.

Alright, enough intro, time to start the article!

To build the report I’ll be using SQL Server 2012, more precisely:

Microsoft SQL Server 2012 (SP1) – 11.0.3000.0 (X64)
Oct 19 2012 13:38:57
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

I’ve made the RDL available for download from my SkyDrive.

The Scenario

You’ve been asked to develop a report that shows a list of products, grouped by category.  The report needs to take a filter on product category into account.  The values on which you need to filter are stored in a configuration table.  You’ve been given a query which for some mystical reason can’t be modified.

Weird enough?  Okay, let’s get that implemented then!

The Report

Let’s first set up a simple report with a dataset and a table.  The table groups the products on category:

A Grouped Table

In Preview it would look like this:

List of products grouped on category

The dataset used in the report above is called ProductList and uses the following query:

select DPC.EnglishProductCategoryName ProductCategoryName
    , DPS.EnglishProductSubcategoryName ProductSubcategoryName
    , DP.EnglishProductName ProductName
from dbo.DimProduct DP
inner join dbo.DimProductSubcategory DPS
    on DPS.ProductSubcategoryKey = DP.ProductSubcategoryKey
inner join dbo.DimProductCategory DPC
    on DPC.ProductCategoryKey = DPS.ProductCategoryKey
order by DPC.EnglishProductCategoryName, DPS.EnglishProductSubcategoryName
    , DP.EnglishProductName;

Retrieving The Filter Configuration

So now we need to filter this report based on configuration stored in a table.  That means we’ll need an additional dataset, let’s use the following query and call it CategoryFilter:

select 'Category' FilterName, 'Components' FilterValue
union all select 'Category', 'Clothing'

(Sure, I’ve hardcoded the configuration data but for scenario’s sake, imagine it’s coming from a table.)

Here’s what the result looks like:

The Category Filter

The dataset contains two fields: the name of the filter and a value on which to filter.  Each value on which we need to filter has its own record.  Having this FilterName field in the table means that it can be re-used for several different filters, if needed.  Your dataset would then use a WHERE FilterName = ‘YourFilter’ clause.

Now, one crucial question remains: how can we use this dataset to filter the data from the other dataset?

Depending on your requirements, there are several possibilities. If you’re sure none of your data regions require the data that will get filtered out, you can use the Filter options on the Dataset.  Alternatively you can use the Filter options on your data region.  In any case, those filters all use the same interface, so implementation-wise it’s all the same.

I’ll implement the filter on the tablix, this gives me the opportunity to show how to get to the properties (dataset is easier).

Okay, so how do we implement a filter on a tablix?

First select the Tablix and right-click the grey square in the top left corner:

Opening the Tablix Properties

Select Tablix Properties and switch to the Filters page.  Click the Add button to add a filter.  As you can see, filters support expressions.  That’s a good thing!

In the Expression combobox, select the field on which you want to filter the data.

The Operator that fits with our requirements should be one that supports multiple values.  In case you’re wondering why, take a good look at our CategoryFilter dataset mentioned earlier.  We want to filter on both Components and Clothing.  So the default equals sign is not really what we’re after, the IN operator will serve much better.

The only remaining empty textbox is Value.  How can we get the values from our filter dataset into this textbox?  In any case, we’ll need to use an expression so click the little fx button next to the Value textbox.

Adding a Filter to the Tablix

As you’re probably aware, a data region can only be linked to one dataset.  Which means we can’t say:

=Fields!FilterValue.Value

because FilterValue doesn’t exist in the dataset that’s linked to the tablix.

So how can we implement a filter based on data from another dataset?  Once again we’ve got several options.  Let’s look into them!

Option One: Report Parameter

If we’d set up a Report Parameter, we could reference that, right?  Let’s close the properties popup for now (click OK) and create a new report parameter:

Adding a report parameter

Our parameter is called CategoryFilter, its type is Text and it should allow multiple values.  We’ll also set visibility to Internal because it doesn’t need to get exposed in any way.

The parameter’s default values are the values retrieved by the CategoryFilter dataset, so switch to the Default Values page and specify the dataset as shown in the screenshot:

Retrieving the default values from a query

With the parameter created, switch back to the Filters page on the Tablix Properties and enter the following expression:

=Parameters!CategoryFilter.Value

If you’ve created the expression by double-clicking the parameter in the Values box, don’t forget to remove the (0) or your data will get filtered on the first item only.

Click OK and render the report:

Report Preview now shows Clothing as first category

It’s working!  Accessories is no longer the first category that gets shown because it’s been filtered out.  The data is now filtered on the configuration as specified through the second dataset.

But… do we really need to set up a report parameter for this?  Well, no!  Let’s investigate option number two.

Option Two: The LookupSet Function

A couple of years ago I wrote an article to explain how you can retrieve data from another dataset through the new lookup functions.  Well, “new” at the time meant SQL Server 2008 R2.  We’re now on 2012 so the functions still exist!

The function that can help us out today is LookupSet.  Open up the Filter properties once again and replace the Value expression with the following:

=LookupSet("Category", Fields!FilterName.Value, Fields!FilterValue.Value, "CategoryFilter")

Close the popup window and preview the report.  If it runs fine, delete the report parameter and run the preview again.

Filtering the data using the LookupSet function

Yes, it still works, nice!  So we don’t need to use a report parameter to filter our data, we can use a fairly simple expression using the LookupSet function!

Option Three: The Split Function

To finalize let’s investigate a variation on the requirement.  In this variation, the filter configuration doesn’t need to come from a table.  It can just be hardcoded in the report.  Can we do that, without using an additional dataset?  Yes we can!

In the Filter properties, change the Value expression to:

="Components,Clothing"

Now render the report:

Oh no, the data is gone!

Hmm, that didn’t work well.  Ow right, the IN operator expects an array of string values and not a comma-separated value string.  Let’s see, how can we get an array out of a character-separated value string?  Actually, I’ve covered this in one of my #tsql2sday posts.  We can use the Split function:

=Split("Components,Clothing", ",")

With that expression specified, let’s render the report a last time:

Filtering the tablix using the Split function

Woohoo, it works once again!

Conclusion

In this article I’ve demonstrated three different possibilities to implement filtering on multiple values on the report side.  It is not a recommended method but in some cases it can be very useful, especially when you don’t have another choice!

Have fun!

Valentino.

Share

Tags: , , , ,

« Older entries

© 2008-2013 A Developer's Blog All Rights Reserved