title: Pivots with dynamic columns in SQL Server
body: <p>I am working on an SQL Query using pvots with dynamic columns in SQL Server (T-sql). 
  Rather than submitting my lengthy query, I’m illustrating my problem with a simplified model. </p>
  
  <p>I create 2 tables: Table1 and Table2 and populate them with a few entries as follows: </p>
  
  <p>Table1:</p>
  
  <hr>
  
  <blockquote>
    <p>Col_ID1...............Col_Name </p>
    
    <p>1.........................Jan-11 </p>
    
    <p>2.........................Feb-11 </p>
    
    <p>3.........................Mar-11 </p>
  </blockquote>
  
  <p>Table2:</p>
  
  <hr>
  
  <blockquote>
    <p>Col_ID2......Account.....AccountName......Amount </p>
    
    <p>1...............121...........Electricity............10000 </p>
    
    <p>2...............121...........Electricity............20000 </p>
    
    <p>3...............121...........Electricity............30000 </p>
    
    <p>1...............122...........Telephone..............100 </p>
    
    <p>2...............122...........Telephone..............200 </p>
    
    <p>3...............122...........Telephone..............300 </p>
  </blockquote>
  
  <p>I am creating a Pivot, but I want the column names to be generated parametrically (based on dates keyed in from the input screen), and not hard coded. </p>
  
  <p>The Query below works well, but gives only a few columns as foll: </p>
  
  <blockquote>
    <p>Jan-11...........Feb-11...........Mar-11 </p>
    
    <p>10,000.00......20,000.00......30,000.00 </p>
    
    <p>100.00...............200.00...........300.00 </p>
  </blockquote>
  
  <p>I want the query to return the descriptive columns also, as foll: </p>
  
  <blockquote>
    <p>Account...........AccountName...........Jan-11............Feb-11..............Mar-11</p>
    
    <p>121.................Electricity..................10,000.00......20,000.00..........30,000.00 </p>
    
    <p>122.................Telephone.....................100.00...........200.00.............300.00 </p>
  </blockquote>
  
  <p>Could anybody please help me modify my query so that I can achieve my objective? </p>
  
  <p>This query is an adaptation of the following article written by Dr. Andras in Sept 2007. 
  <a href="http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx">http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx</a> </p>
  
  <p>Somebody remarked that the code could be subject to Injection Attacks and proposed to use Quotename function instead of concatenating square brackets. </p>
  
  <p>Could you explain how to use Quotename in my query. </p>
  
  <p>Thanks a lot, </p>
  
  <p>Leon Lai 
  .<br>
  .<br>
  .    </p>
  
  <p>Here’s my Query:   </p>
  
  <p>------------------------ create &amp; populate table1 -------------------------------- </p>
  
  <pre><code>CREATE TABLE Table1
  (Col_ID1 INT, 
  Col_Name varchar(10))  
  
  INSERT INTO Table1 VALUES (1, 'Jan-11')  
  INSERT INTO Table1 VALUES (2, 'Feb-11')  
  INSERT INTO Table1 VALUES (3, 'Mar-11') 
  </code></pre>
  
  <p>-------------------------create &amp; populate table2 ----------------------------------  </p>
  
  <pre><code>CREATE TABLE Table2  
  (Col_ID2 INT,  
  Account varchar(10),  
  AccountName varchar(20),  
  Amount numeric(18,6))  
  
  INSERT INTO Table2 VALUES (1, 121, 'Electricity', 10000)  
  INSERT INTO Table2 VALUES (2, 121, 'Electricity', 20000)  
  INSERT INTO Table2 VALUES (3, 121, 'Electricity', 30000)  
  INSERT INTO Table2 VALUES (1, 122, 'Telephone', 100)        
  INSERT INTO Table2 VALUES (2, 122, 'Telephone', 200)   
  INSERT INTO Table2 VALUES (3, 122, 'Telephone', 300)   
  </code></pre>
  
  <p>---------------------------------- create columns headings -------------------   </p>
  
  <pre><code>DECLARE @cols NVARCHAR(2000)   
  SELECT @cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT   
  '],[' + t2.Col_Name   
  FROM Table1 AS t2   
  ORDER BY '],[' + t2.Col_Name 
  FOR XML PATH('')   
  ), 1, 2, '') + ']'   
  </code></pre>
  
  <p>------------------------------------- create @query ----------------------    </p>
  
  <pre><code>DECLARE @query NVARCHAR(4000)   
  
  SET @query = N'SELECT '+   
  @cols +' 
  
  FROM   
  </code></pre>
  
  <p>--------------------------subquery-----   </p>
  
  <p><code>(SELECT<br>
      t1.Col_Name,<br>
      t2.Account,<br>
      t2.Amount<br>
      FROM Table1 AS t1<br>
      JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2<br>
      ) p</code></p>
  
  <p>--------------------pivot -------------------------  </p>
  
  <p><code>PIVOT<br>
  (<br>
  Sum ([Amount] )<br>
  FOR Col_Name IN<br>
  ( '+<br>
  @cols +' )<br>
  ) AS pvt '
  </code> </p>
  
  <p>----------------------exec &amp; drop----------   </p>
  
  <pre><code>EXECUTE(@query)
  drop table table1
  drop table table2
  </code></pre>
  
  <p>=======================================================</p>
  
  <p>Hi Philip,</p>
  
  <p>Thanks a lot for your reply.</p>
  
  <p>Your proposed query works smoothly, and generates the expected screen, but it is not exactly what I wanted.</p>
  
  <p>First, thanks for the code:
  SELECT @cols = isnull (@cols + ',' , ' ' ) + '[' + Col_Name + ']'</p>
  
  <p>It is simpler and does replace my line involving stuff and xml path, apparently with same effect.</p>
  
  <p>Let me explain what I want to do.</p>
  
  <p>I want to develop a query in Sap Business 1 (An Accounting Package - or call it an ERP).
  Sap uses T-sql in Microsoft Server 2008, and has its own query generator. 
  With very few exceptions, Sap sql is similar to T-sql.</p>
  
  <p>I want my query to give a list of all income and expenses month by month over a 12-month period.</p>
  
  <p>However, I don't want my column headings to be hardcoded, (as this would require me to amend my query from time to time) as follows:</p>
  
  <p>Jan-11, Feb-11, Mar-11, Apr-11, ..... Dec-11</p>
  
  <p>Rather, I want the column headings to be Dynamically generated from the dates which the user enters in the input screen.</p>
  
  <p>As I mentioned, the query which I posted on the forum is an over-simplified version of my real query, used only for illustration. The real query contains several variables and an input screen (called Query - Selection Criteria box in Sap b1) permits the user to enter a date. It is this date which will be used to determine the column names dynamically.</p>
  
  <p>This is why I needed such complicated tools as  @cols, @query, pivot etc.</p>
  
  <p>If I input, say '01.06.11' (01 Jun 2011) in the input screen, this date will be passed on to the sql which will determine the names of the column headings as foll:</p>
  
  <p>Jun-11, Jul-11, Aug-11 ..... May-12.</p>
  
  <p>If I input another date, say '01.09.10' (01 Sep 2010), the column headings will change to:</p>
  
  <p>Sep-10, Oct-10, .... Aug-11</p>
  
  <p>It seems that you have hardcoded my column headings.</p>
  
  <p>Could you have a second look at my query, and propose something that will allow the column names to be generated parametrically instead of being hard coded?</p>
  
  <p>Thanks</p>
  
  <p>Leon Lai</p>