ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel
  • »
  • Technology»
  • Computers & Software»
  • Computer Science & Programming

How-To Develop CrossTab Queries in T-SQL(Transact-SQL) with Dynamic Columns

Updated on March 7, 2012

Dynamic Cross Tab Queries in T-SQL

© Kevin Languedoc 2010

Creating Cross Tab Style queries in SQL Server is always a challenge. Several design pattern have emerge over the years that I always found to be a bit lacking. This tutorial will demonstrate a simple but very powerful way to create Cross Tab queries with Dynamic Columns. By this I mean that you don’t know the column names beforehand.

My method involves using “For XML” which was also introduced with SQL Server 2000 to provide a means to do string concatenation. This was further expanded with SQL Server 2005 to include the PATH clause which we will use to generate our dynamic columns. The rest of this article will demonstrate where to use For XML Path along with Pivot which was introduced SQL Server 2005 to create a flexible cross tab solution with dynamic columns.

I am going to perform the following steps:

  1. Create variables
  2. Select the values for my dynamic columns as xml
  3. Convert the xml into a string
  4. Write the query
  5. Execute the query

Create the variables

We are going to need three variables for this example: One for the XML, one for the SQL query and one for the column string. @SQL is for the SQL query; @XML is for the XML that will be created with For XML Path and finally @Cols for the column string to be used in the Pivot procedure:

Declare @SQL VARCHAR(8000),
@Cols VARCHAR(4000)

Next we are going to get our list of columns based on the values of a query that will return a list of values that can be used as columns names. In the following query we are selecting a list of products names from the ProductsCatalog table. The one caveat is that the values we are selecting here must also be in the table we will use for our cross tab query.

We will then enclose them in square brackets because the Pivot function in SQL server requires it as part of it syntax. This is a straightforward SELECT that I will assign to my @Cols variable. This query can as complex as you need it to be to return a single columns of values for the column headers in the Cross Tab result set.

Set @COL = (SELECT ', [' + Products + ']'
FROM ProductsCatalog

The XML output would be like this:

<Products>,[Widget1] </Products>
<Products>,[Widget2] </Products>
<Products>,[Widget3] </Products>
<Products>,[Widget4] </Products>
<Products>,[Widget5] </Products>
<Products>,[Widget6] </Products>

However you would actually see the results in SSMS as a hyperlinked result as follows:


If you wanted to see the actual XML as above you would need to click on the results link. Next we need to convert this XML to a string which we will do as in the following section.

Convert the XML into a string

Converting the XML output to a string is quite straightforward. All you do is convert your XML to VARCHAR and specify that you only want DISTINCT values. You assign this string to a variable as you can see below.


The second SET is to remove the leading comma“,” from the string.


Now the only two steps left are to write the Query including the PIVOT clause and execute the query. First the query, here I am using a Select clause to retrieve the columns for my Pivot. The data is coming from the subquery and is used to sum the values in the val column using FOR [col3] clause. Notice the col3 column is enclosed in square brackets [] and is the same column that was used in the selection of the column names in the previous query. Finally, the columns names are enclosed in another set of parentheses and the PIVOT must be assigned an alias like “pt”. The same nomenclature applies to the data query; it must have an alias such as “data”. To finish off, the query is executed with a simple Exec(@Sql).

SET @SQL = 'Select * from
Select products, salesValues
from ProductSales
) data
Sum(salesValues) FOR [products] IN ('+@Cols +')
) pt'

This is a very simple example to explain the concepts in a, hopefully, clear way. This pattern lays out a simple and highly dynamic method of generating dynamic columns for your cross tab queries.


    0 of 8192 characters used
    Post Comment

    • klanguedoc profile image

      Kevin Languedoc 5 years ago from Canada

      Sorry Val. So I guess there are different ways to implement this design.

    • profile image

      Val 5 years ago

      Kevin , columns are not hardcoded. In both examples the data retrieval is in 3 commands.

    • klanguedoc profile image

      Kevin Languedoc 6 years ago from Canada

      Yes but your column names are hard coded. In the above example they are dynamic. For example if you were to display monthly sales only for months were there are sales.

      The first example is similar to mine (r-tag), but I believe mine is simpler to implement and I use hundreds of times in various implementations.


    • profile image

      Val 6 years ago

      Kevin , You can simplify the preparation of the columns list. Check these articles where dynamic pivot is created using STUFF function: