Solved

Is it possible to write a SQL query with dynamic columns?

Posted on 2009-07-08
7
544 Views
Last Modified: 2012-05-07
I have a query for a revenue report, and want to know if there is a way to have the column names in my query auto-populated from a field value in a table.  The table I am using has unique groups names that I want to use as the column heading for each group so that I do not have to hard code the column name in my query.  There is a possibility that new group names will be added or existing ones could be changed.  Therefore, I need a query that will dynamically populate these group names for its respective columns.  In my query below, I assign a static column name to each field / sub-query.  I would like to dynamically pull the group name for each releated sub query.  I would also like to avoid hard-coding the group name in WHERE clause of the sub queries (e.g. AND d1.groupkey = 'INSPECTION').  Is there a way to do this?

THANK YOU in advance,

Parachute

Note:  The database is SQL Server 2000
SELECT DISTINCT 'Office' = a.office
	,'Customer' = a.name
	,'Invoice' = a.invno
	,'Jtype' = a.job_type
	,'Inv Date' = a.invdate
	,'Asset Sale' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 WHERE b1.invno = b.invno AND b1.itype = 'X'),0)
	,'Bid Job' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'BID JOB'),0)
	,'Inspection' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'INSPECTION'),0)
    ,'Labor' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b1.invno = b.invno AND b1.itype <> 'X' AND d1.groupkey = 'LABOR'),0)
	,'M&S Sale/Repairs' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'M&S SALE / REPAIRS'),0)
    ,'Mile/Sub' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'MILE/SUB'),0)
    ,'Re-Rent' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'RERENT EQUIPMENT'),0)
	,'Tool Rental' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X'	AND d1.groupkey = 'TOOL RENTAL'),0)
	,'Trucking' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'TRUCKING'),0)
	,'Waste Disposal' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 INNER JOIN inventory c1 ON b1.item = c1.item INNER JOIN categories d1 ON c1.cat = d1.category WHERE b.invno = b1.invno AND b1.itype <> 'X' AND d1.groupkey = 'WASTE DISPOSAL'),0)
	,'Other' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 WHERE b.invno = b1.invno AND b1.itype <> 'X' AND b1.item = 'COMMENT'),0)
	,'Gross Total' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 WHERE b.invno = b1.invno),0)
	,'Discount' = COALESCE(((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))) * (b1.discount * b1.discountable)/100,2)) FROM invoiceitem b1 WHERE b.invno = b1.invno)),0) 
	,'Net Total' = COALESCE((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))),2)) FROM invoiceitem b1 WHERE b.invno = b1.invno),0) - 
				   COALESCE(((SELECT SUM(ROUND(((b1.quant * b1.min_chg) + (b1.quant * (b1.aday * b1.adamt))) * (b1.discount * b1.discountable)/100,2)) FROM invoiceitem b1 WHERE b.invno = b1.invno)),0)
FROM invoicehdr a
INNER JOIN invoiceitem b ON a.invno = b.invno
INNER JOIN inventory c ON b.item = c.item
INNER JOIN categories d ON c.cat = d.category
LEFT OUTER JOIN taxcode e ON a.taxcode = e.taxcode 
WHERE a.invdate BETWEEN '2009-04-01 00:00:00.000' AND '2009-06-30 23:59:59.000'
ORDER BY a.office, a.name, a.invno, a.invdate

Open in new window

0
Comment
Question by:parachute_505
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
7 Comments
 
LVL 57

Accepted Solution

by:
Raja Jegan R earned 500 total points
ID: 24809824
Yes.. You have and try like this.
Using a simple query for explanation:

In the example below, you can
1. Dynamically pass column selections @ur_dynamic_column
2. Dynamically pass column names / results @ur_dynamic_column_name
3. Dynamically pass where condition variables @a
4. Dynamically pass AND Conditions stored in some table or variable (SELECT dynamic_where_condition from some_table where a = 1)  or @b like that.

Hope this helps
declare @sql nvarchar(2000);
set @sql = ' select a, ' + @ur_dynamic_column + ' ,c as ' + @ur_dynamic_column_name + ' from ur_table where a = ' + @a + (SELECT dynamic_where_condition from some_table where a = 1) 
exec sp_executesql @sql;

Open in new window

0
 
LVL 57

Expert Comment

by:Raja Jegan R
ID: 24809828
Since the database is SQL Server 2000, a slight modification required.
declare @sql varchar(2000);
set @sql = ' select a, ' + @ur_dynamic_column + ' ,c as ' + @ur_dynamic_column_name + ' from ur_table where a = ' + @a + (SELECT dynamic_where_condition from some_table where a = 1) 
exec (@sql);

Open in new window

0
 

Author Comment

by:parachute_505
ID: 24817029
rrjegan17:

I don't quite understand how I can incorporate what you wrote into my query.  

Parachute
0
 
LVL 57

Expert Comment

by:Raja Jegan R
ID: 24819916
>> Therefore, I need a query that will dynamically populate these group names for its respective columns. In my query below, I assign a static column name to each field / sub-query.  

If I understood correctly, then you mean to say that column names to be displayed will be changed dynamically in your SELECT query. If that is the case, then it is step no 2 in comment 24809824.

Follow the example provided earlier.

>> I would like to dynamically pull the group name for each releated sub query.  
I would also like to avoid hard-coding the group name in WHERE clause of the sub queries (e.g. AND d1.groupkey = 'INSPECTION').

In that case I assume that your WHERE clause will be dynamically added to your query. Kindly follow step no 3 and 4 above in that case.

Hope this clarifies.
Revert if I need to explain it in more detail
0
 
LVL 57

Expert Comment

by:Raja Jegan R
ID: 25562083
Split between 24809828 and 24819916
0

Featured Post

Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Confronted with some SQL you don't know can be a daunting task. It can be even more daunting if that SQL carries some of the old secret codes used in the Ye Olde query syntax, such as: (+)     as used in Oracle;     *=     =*    as used in Sybase …
If you have heard of RFC822 date formats, they can be quite a challenge in SQL Server. RFC822 is an Internet standard format for email message headers, including all dates within those headers. The RFC822 protocols are available in detail at:   ht…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question