ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel

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 imageAUTHOR

      Kevin Languedoc 

      6 years ago from Canada

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

    • profile image


      6 years ago

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

    • klanguedoc profile imageAUTHOR

      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


      6 years ago

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


    This website uses cookies

    As a user in the EEA, your approval is needed on a few things. To provide a better website experience, uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

    For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at:

    Show Details
    HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
    LoginThis is necessary to sign in to the HubPages Service.
    Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
    AkismetThis is used to detect comment spam. (Privacy Policy)
    HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
    HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
    Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
    CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
    Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the or domains, for performance and efficiency reasons. (Privacy Policy)
    Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
    Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
    Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
    Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
    Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
    VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
    PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
    Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
    MavenThis supports the Maven widget and search functionality. (Privacy Policy)
    Google AdSenseThis is an ad network. (Privacy Policy)
    Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
    Index ExchangeThis is an ad network. (Privacy Policy)
    SovrnThis is an ad network. (Privacy Policy)
    Facebook AdsThis is an ad network. (Privacy Policy)
    Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
    AppNexusThis is an ad network. (Privacy Policy)
    OpenxThis is an ad network. (Privacy Policy)
    Rubicon ProjectThis is an ad network. (Privacy Policy)
    TripleLiftThis is an ad network. (Privacy Policy)
    Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
    Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
    Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
    Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
    ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
    Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)