Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server 2005 Pivot on Unknown Number of Columns

Tags:

I am working with a set of data that looks something like the following.

StudentName  | AssignmentName |  Grade --------------------------------------- StudentA     | Assignment 1   | 100 StudentA     | Assignment 2   | 80 StudentA     | Total          | 180 StudentB     | Assignment 1   | 100 StudentB     | Assignment 2   | 80 StudentB     | Assignment 3   | 100 StudentB     | Total          | 280 

The name and number of assignments are dynamic, I need to get results simlilar to the following.

Student      | Assignment 1  | Assignment 2  | Assignment 3  | Total -------------------------------------------------------------------- Student A    | 100           | 80            | null          | 180 Student B    | 100           | 80            | 100           | 280 

Now ideally I would like to sort the column based on a "due date" that could be included/associated with each assignment. The total should be at the end if possible (It can be calculated and removed from the query if possible.)

I know how to do it for the 3 assignments using pivot with simply naming the columns, it is trying to do it in a dynamic fashion that I haven't found a GOOD solution for yet. I am trying to do this on SQL Server 2005

EDIT

Ideally I would like to implement this WITHOUT using Dynamic SQL, as that is against the policy. If it isn't possible...then a working example with Dynamic SQL will work.

like image 524
Mitchel Sellers Avatar asked Oct 17 '08 20:10

Mitchel Sellers


People also ask

What are the limitations of the PIVOT operator in T SQL?

The design of the PIVOT and UNPIVOT operators sometimes leads to bugs and pitfalls in your code. The PIVOT operator's syntax doesn't let you explicitly indicate the grouping element. If you don't realize this, you can end up with undesired grouping elements.

Can you PIVOT in SQL without aggregate function?

The answer is no: PIVOT requires aggregation.

When to use dynamic SQL?

You should use dynamic SQL in cases where static SQL does not support the operation you want to perform, or in cases where you do not know the exact SQL statements that must be executed by a PL/SQL procedure. These SQL statements may depend on user input, or they may depend on processing work done by the program.


2 Answers

I know you said no dynamic SQL, but I don't see any way to do it in straight SQL.

If you check out my answers to similar problems at Pivot Table and Concatenate Columns and PIVOT in sql 2005

The dynamic SQL there is not vulnerable to injection, and there is no good reason to prohibit it. Another possibility (if the data is changing very infrequently) is to do code-generation - instead of dynamic SQL, the SQL is generated to a stored procedure on a regular basis.

like image 196
Cade Roux Avatar answered Sep 27 '22 19:09

Cade Roux


To PIVOT this data using dynamic sql you can use the following code in SQL Server 2005+:

Create Table:

CREATE TABLE yourtable     ([StudentName] varchar(8), [AssignmentName] varchar(12), [Grade] int) ;  INSERT INTO yourtable     ([StudentName], [AssignmentName], [Grade]) VALUES     ('StudentA', 'Assignment 1', 100),     ('StudentA', 'Assignment 2', 80),     ('StudentA', 'Total', 180),     ('StudentB', 'Assignment 1', 100),     ('StudentB', 'Assignment 2', 80),     ('StudentB', 'Assignment 3', 100),     ('StudentB', 'Total', 280) ; 

Dynamic PIVOT:

DECLARE @cols AS NVARCHAR(MAX),     @query  AS NVARCHAR(MAX)  select @cols = STUFF((SELECT distinct ',' + QUOTENAME(AssignmentName)                      from yourtable             FOR XML PATH(''), TYPE             ).value('.', 'NVARCHAR(MAX)')          ,1,1,'')  set @query = 'SELECT StudentName, ' + @cols + ' from               (                 select StudentName, AssignmentName, grade                 from yourtable             ) x             pivot              (                 min(grade)                 for assignmentname in (' + @cols + ')             ) p '  execute(@query) 

See SQL Fiddle with Demo

The result is:

| STUDENTNAME | ASSIGNMENT 1 | ASSIGNMENT 2 | ASSIGNMENT 3 | TOTAL | -------------------------------------------------------------------- |    StudentA |          100 |           80 |       (null) |   180 | |    StudentB |          100 |           80 |          100 |   280 | 
like image 43
Taryn Avatar answered Sep 27 '22 20:09

Taryn