Saturday, May 7, 2011

Aggregation Of Strings In T-SQL

Suppose, you have a scenario where you need to group by some column and in the mean time aggregate (concatenation of string in our case) "strings"... how can we do that?

Well, there are numerous methods, Anith, has given a detailed method about them which could be found in his blog at http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/.

However, the one, which I liked was by using FOR XML PATH.

Let's see the demonstration -

1. Create a table where we have two columns A (for grouping) and B (for concatenation of strings) and then insert some dummy values -

DECLARE @table Table(A INT, B VARCHAR)
INSERT INTO @table VALUES(1,'A') ,(1,'B'),(1,'C'),(2,'X'),(2,'Y'),(2,'Z')
 
2. Now type following query, which will achieve the desired result -
 
SELECT T1.A,( SELECT B + ',' FROM @table T2 WHERE T2.A = T1.A FOR XML PATH('')) AS B
FROM @table T1
GROUP BY A ;
 
and the desired output is -
 
A          B
1        A,B,C
2        X,Y,Z
 
FOR XML PATH is used to generate XML code from the SQL.
 
This solution is tricky but elegant!

Tuesday, March 22, 2011

Dynamic Redirection of Rows to Designated "Folders\Files"

Today, we will see how we can redirect rows from a database table to designated folder and then a file dynamically. Let me explain the scenario first -

We have a table say Test, having following instance:












Now, if you notice we have S1, S2, S3, S4 and S5 as 5 distinct ‘SubCategory’. We have one root folder, say, D:\RootFolder, inside this root folder 5 folders (S1..S5) would be created dynamically and in each folder a text file would be created for that day where rows would be copied based on the subcategory. So in folder S1 a file S1_20110321.txt would be created and all the records pertaining to ‘S1’ would be copied here. Similary all the records pertaining to Si subcateogry would be redirected to Si folder and copied to Si_today'sdate.txt file.

Let's see how we can implement it. First of all we would require three variables, objSubCat, strQuery and strSubCat. objSubCat is a Object variable to store the record set fetched from the DB, strQuery is used to store a string for creating DB query and strSubCat is used for storing the subcategory.

We also need to make sure that value of strQuery should change dynamically in order to fetch the correct recordset, hence, we'd be using expression to achieve dynamic behavior. Following screen shot shows the expression settings -

 














Below screen shot shows these variables and their default value -




Now, we would create an ExecuteSQL task to store all the distinct SubCategory in objSubCat variable. Then based on objSubCat variable ForEachLoop would process the data accordingly. Following screen shot is how our package would look like -
















Now, I'll show you how to configure each task in the control flow to achieve the given scenario.

1. Exectue SQL Task: This task is used to store all the distinct SubCategory to an object variable objSubCat. Following two screen shot shows how I have configured General and Result Set of Execute SQL task.

(a) General:















(b) Result Set:














Once this task is executed in run time it will store distinct sub categories in objSubCat variable which would be used for looping the data set.

2. FOREACH Loop Task: Foreach loop will iterate based on the objSubCat variable. Since we can't use object variables in the expressions we need to assign value of objSubCat to some other 'non-object' variable and here we would use strSubCat. Following are the configuration used for this task.

(a) Collection:
















(b) Variable Mappings:


3. File System Task: This task will create folder at run time dynamically. Following are the configuration which are used to achieve it.                                                                                                                

















Following screen shot shows setting about Source Connection property.


 Following screen shot shows setting about Source Connection property -


"D:\\RootFolder\\" +  @[User::strSubCat]    
                                                                                                                     


4. Data FlowTask: This task is the main task which will used all the configuration we have done and would  redirect records accordingly. Following components are used -                                                             



OLEDB Source is used for fetching the records from the DB Test table dynamically based on the iteration     state. The query gets generated dynamically for the query variable. Please refer below screen shot for the      details -                                                                                                                                         

















Once this is done we just need to configure Flat File destination. The setting is simple, we just need to configure Flat File Connection manager's Connection String dynamically. Following dynamic string is used to achieve this -

"D:\\RootFolder\\" +  @[User::strSubCat] +"\\"+@[User::strSubCat] +"_"+ (DT_STR, 14, 1252)  datepart ("yyyy",getdate()) + (DT_STR, 14, 1252)  datepart ("mm",getdate()) + (DT_STR, 14, 1252)  datepart ("dd",getdate()) + ".txt"

















It's done. Now, just run the package and see if folders like 'S1', 'S2' etc are created inside D:\RootFolder  and there are text files with correct records.

Hope you find it interesting and please let me know your feedback, any better approach would be highly appreciating.

Sunday, March 20, 2011

"ContributionToParent" Calculation

Today, we will see a simple but important calculation which is often used in data analysis and that is “Percentage Contribution to its Parent” calculation. Let’s take an example where we have a state Maharashtra having 3 cities Mumbai, Pune and Nagpur where we need to analyze the sales data. Total sale of the state is say 1000$s for some random year, whereas total sale in Mumbai, Pune and Nagpur is 600$, 400$ and 200$ respectively so contribution of Mumbai for Maharashtra would be (600*100/1000) i.e. 60% and similarly for Pune and Nagpur would be 40% and 20% respectively.
Now we will see how we can simulate this scenario in SSAS 2008.
Let’s create a simple cube having following schema. (Assuming reader can create it very quickly without much guidance or can create their own test cube, concept would be the same!)


Now, we will create a calculated member, say ContributionToParent, please see below screen shot for configuring it –
Following MDX expression is used to evaluate the calculated member –

([Measures].[Sales]) / ([Measures].[Sales],[DimGeo].[DimGeo].CurrentMember.Parent)
You can try this on your own test cube and then can test data manually and then from cube browser, result would be the same!

Friday, March 18, 2011

Contextual or Correlated Charting

Sometime we need to create charts which are contextual in nature i.e. their data is based on data selected from some other report item like some column field etc. E.g. in the following screen shot if you click on any Category field say "C3" the data for the pie chart would change accordingly.








Designing such report is quiet simple. You just need to create two different datasets one for the table and the other for the chart. Dataset for the chart would be parameterized and the parameter value would be passed from the field you selected in the table (Category like C1, C2 etc. in our case)


Let's come into the implementation part. Follow below steps -

Step 1: Create a data set for the table report item using below query:

SELECT 'C1' AS Category, 4 AS Pass, 6 AS Fail
UNION ALL
SELECT 'C2' AS Category, 5 AS Pass, 5 AS Fail
UNION ALL
SELECT 'C3' AS Category, 6 AS Pass, 4 AS Fail
UNION ALL
SELECT 'C4' AS Category, 7 AS Pass, 3 AS Fail

Step 2: Create another, parameterized dataset using below query:

SELECT Category, Pass, Fail
FROM (SELECT 'C1' AS Category, 4 AS Pass, 6 AS Fail
UNION ALL
SELECT 'C2' AS Category, 5 AS Pass, 5 AS Fail
UNION ALL
SELECT 'C3' AS Category, 6 AS Pass, 4 AS Fail
UNION ALL
SELECT 'C4' AS Category, 7 AS Pass, 3 AS Fail) AS X
WHERE (Category = @CategoryParam)

Step 3: Configure Table using dataset created in step 1 and configure Chart using dataset created in Step 2.

Step 4: Now, the important part, right click the Category text box and configure the Text Box properties as per the below screen shot -













You need to configure Action and set parameter value so that data for pie chart is selected accordingly.

You are done, you can select any of the category and data of pie chart would change accordingly. Isn't this so simple? Please let me know if you have a better way to do this.

Sunday, February 13, 2011

How to count total rows in a table without count(*)?

SELECT rows FROM sys.partitions WHERE object_id = object_id('test');