SQL Stored procedure, Output rows as columns for summary - sql

Using SQL 2005
Here is what my SQL results look like
UserID | Frame | Choice | Description | DateTime
------------------------------------------------
bcn005 | PL_P03| 1 | Rules-Based | 2011-10-24 14:14:26
bcn005 | PL_P04| 0 | VirtueBased | 2011-10-24 14:16:37
...
bmk172 | Prac_1| 0 | None | 2011-10-25 12:45:38
...
My client wants the results to look like this
UserID | Frame | Choice | Description | DateTime | Frame | Choice | Description | DateTime
-------------------------------------------------------------------------------------------
bcn005 | PL_P03| 1 | Rules-Based | 2011-10-..| PL_P04| 0 | VirtueBased | 2011-10-..
bmk172 | Prac_1| 0 | None | 2011-10-..|
Where all of a participants responses are on one row. There basically needs to be another set of Frame/Choice Description/DateTime for every row of the result set.
These are survey results, but it is the type of survey where one participant might have went back and changed their answer 5 times. So the amount of Frame/Choice Description/DateTime for each UserID will be different.
I know I should use a stored procedure (or maybe even an excel macro) but I am completely new to both of these. Any guidance is appreciated. Here is my SQL query
select UserID, locationName AS 'Frame', student_response AS 'Choice',
description, DateTime
from tblStudentResponses
WHERE GroupID in (18,20,21,36,37,38,39,40)
AND UserID in (SELECT UserID FROM tblStudentResponses WHERE
locationName = 'Character1Certificate')
AND DateTime > '2011-10-01'
AND type = 'choice'
order by UserID
!! UPDATE !! Full working solution and test code
--Sample Data Preperation
DECLARE #FrameChoices as TABLE(UserId varchar(50),Frame varchar(50),Choice varchar(4000),Description varchar(1000),[DateTime] DateTime)
--Test Values
INSERT INTO #FrameChoices(UserId,Frame,Choice,Description,[DateTime])
SELECT UserId,Frame,Choice,Description,[DateTime]
FROM (
SELECT 'bcn005' AS UserId, 'PL_P03' AS Frame, '1' AS Choice, 'Rules-Based'
AS Description, '2011-10-24 14:14:26' AS [DateTime]
UNION ALL
SELECT 'bcn005' AS UserId, 'PL_P04' AS Frame, '0' AS Choice, 'VirtueBased'
AS Description, '2011-10-24 14:16:37' AS [DateTime]
UNION ALL
SELECT 'bmk172' AS UserId, 'Prac_1' AS Frame, '0' AS Choice, 'None' AS
Description, '2011-10-25 12:45:38' AS [DateTime]
) T
-- Dynamic SQL Preparation
DECLARE #SQL VARCHAR(MAX)
DECLARE #MaxNumberOfFrames INT
SET #SQL = ''
SET #MaxNumberOfFrames = 1
SELECT #MaxNumberOfFrames = MAX(FrameCount)
FROM
(
SELECT COUNT(1) FrameCount
FROM #FrameChoices
GROUP BY UserId
) T
--needed to be part of the SQL string to EXEC at the bottom
SET #SQL = 'DECLARE #FrameChoices as TABLE(UserId varchar(50),Frame varchar(50),Choice varchar(4000),Description varchar(1000),[DateTime] DateTime)'
SET #SQL = #SQL + ' INSERT INTO #FrameChoices(UserId,Frame,Choice,Description,[DateTime])'
SET #SQL = #SQL + ' SELECT UserId,Frame,Choice,Description,[DateTime]'
SET #SQL = #SQL + ' FROM ('
SET #SQL = #SQL + ' SELECT ''bcn005'' AS UserId, ''PL_P03'' AS Frame, ''1'' AS Choice, ''Rules-Based'''
SET #SQL = #SQL + ' AS Description, ''2011-10-24 14:14:26'' AS [DateTime]'
SET #SQL = #SQL + ' UNION ALL'
SET #SQL = #SQL + ' SELECT ''bcn005'' AS UserId, ''PL_P04'' AS Frame, ''0'' AS Choice, ''VirtueBased'''
SET #SQL = #SQL + ' AS Description, ''2011-10-24 14:16:37'' AS [DateTime]'
SET #SQL = #SQL + ' UNION ALL'
SET #SQL = #SQL + ' SELECT ''bmk172'' AS UserId, ''Prac_1'' AS Frame, ''0'' AS Choice, ''None'' AS'
SET #SQL = #SQL + ' Description, ''2011-10-25 12:45:38'' AS [DateTime]'
SET #SQL = #SQL + ' ) T'
SET #SQL = #SQL + ' SELECT UserId'
--changed size to max
DECLARE #ColumnSQL VARCHAR(MAX)
DECLARE #CurrentFrame INT
SET #CurrentFrame = 1
WHILE (#CurrentFrame <= #MaxNumberOfFrames)
BEGIN
SET #ColumnSQL = ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN Frame ELSE '''' END) AS Frame_'+CAST(#CurrentFrame AS VARCHAR)
+ ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN Choice ELSE '''' END) AS Choice_'+CAST(#CurrentFrame AS VARCHAR)
+ ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN Description ELSE '''' END) AS Description_'+CAST(#CurrentFrame AS VARCHAR)
+ ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN [DateTime] ELSE NULL END) AS DateTime_'+CAST(#CurrentFrame AS VARCHAR)
SET #SQL = #SQL + #ColumnSQL
SET #CurrentFrame = #CurrentFrame + 1
END
SET #SQL = #SQL + ' FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM #FrameChoices) T GROUP BY T.UserId'
PRINT #SQL
-- This generated SQL then can be executed by
EXEC(#SQL)
-- OR
EXEC SP_EXECUTESQL(#SQL)
-- Sample SQL generated from above query
DECLARE #FrameChoices as TABLE(UserId varchar(50),Frame varchar(50),Choice varchar(4000),Description varchar(1000),[DateTime] DateTime) INSERT INTO #FrameChoices(UserId,Frame,Choice,Description,[DateTime]) SELECT UserId,Frame,Choice,Description,[DateTime] FROM ( SELECT 'bcn005' AS UserId, 'PL_P03' AS Frame, '1' AS Choice, 'Rules-Based' AS Description, '2011-10-24 14:14:26' AS [DateTime] UNION ALL SELECT 'bcn005' AS UserId, 'PL_P04' AS Frame, '0' AS Choice, 'VirtueBased' AS Description, '2011-10-24 14:16:37' AS [DateTime] UNION ALL SELECT 'bmk172' AS UserId, 'Prac_1' AS Frame, '0' AS Choice, 'None' AS Description, '2011-10-25 12:45:38' AS [DateTime] ) T SELECT UserId, MAX(CASE WHEN RowNumber =1 THEN Frame ELSE '' END) AS Frame_1, MAX(CASE WHEN RowNumber =1 THEN Choice ELSE '' END) AS Choice_1, MAX(CASE WHEN RowNumber =1 THEN Description ELSE '' END) AS Description_1, MAX(CASE WHEN RowNumber =1 THEN [DateTime] ELSE NULL END) AS DateTime_1, MAX(CASE WHEN RowNumber =2 THEN Frame ELSE '' END) AS Frame_2, MAX(CASE WHEN RowNumber =2 THEN Choice ELSE '' END) AS Choice_2, MAX(CASE WHEN RowNumber =2 THEN Description ELSE '' END) AS Description_2, MAX(CASE WHEN RowNumber =2 THEN [DateTime] ELSE NULL END) AS DateTime_2 FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM #FrameChoices) T GROUP BY T.UserId

If SQL 2005 or ABove you can try pivot.
If SQL 2000, then use combination of Group By and Case.
SELECT GC1,
GC2,
MAX(CASE WHEN CONDITION1 THEN Value1 ELSE Value2 END) AS DerivedColumn
FROM Table1
GROUP BY GC1, GC2
References:
SQL Server PIVOT and UNPIVOT
Pivot with Dynamic Column
Stack Overflow Pivot Question
[Solution]
-- Sample Data Preparation
DECLARE #FrameChoices TABLE
(
UserId varchar(20),
Frame varchar(20),
Choice int,
Description varchar(20),
[DateTime] DateTime
)
INSERT INTO #FrameChoices(UserId,Frame,Choice,Description,[DateTime])
SELECT UserId,Frame,Choice,Description,[DateTime]
FROM (
SELECT 'bcn005' AS UserId, 'PL_P03' AS Frame, 1 AS Choice, 'Rules-Based' AS Description, '2011-10-24 14:14:26' AS [DateTime]
UNION ALL
SELECT 'bcn005' AS UserId, 'PL_P04' AS Frame, 0 AS Choice, 'VirtueBased' AS Description, '2011-10-24 14:16:37' AS [DateTime]
UNION ALL
SELECT 'bmk172' AS UserId, 'Prac_1' AS Frame, 0 AS Choice, 'None' AS Description, '2011-10-25 12:45:38' AS [DateTime]
) T
-- Dynamic SQL Preparation
DECLARE #SQL VARCHAR(4000)
DECLARE #MaxNumberOfFrames INT
SET #SQL = ''
SET #MaxNumberOfFrames = 1
SELECT #MaxNumberOfFrames = MAX(FrameCount)
FROM
(
SELECT COUNT(1)FrameCount
FROM #FrameChoices
GROUP BY UserId
) T
SET #SQL = 'SELECT UserId'
DECLARE #ColumnSQL VARCHAR(512)
DECLARE #CurrentFrame INT
SET #CurrentFrame = 1
WHILE (#CurrentFrame <= #MaxNumberOfFrames)
BEGIN
SET #ColumnSQL = ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN Frame ELSE NULL END) AS Frame_'+CAST(#CurrentFrame AS VARCHAR)
+ ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN Choice ELSE NULL END) AS Choice_'+CAST(#CurrentFrame AS VARCHAR)
+ ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN Description ELSE NULL END) AS Description_'+CAST(#CurrentFrame AS VARCHAR)
+ ', MAX(CASE WHEN RowNumber ='+CAST(#CurrentFrame AS VARCHAR)+ ' THEN [DateTime] ELSE NULL END) AS DateTime_'+CAST(#CurrentFrame AS VARCHAR)
SET #SQL = #SQL + #ColumnSQL
SET #CurrentFrame = #CurrentFrame + 1
END
SET #SQL = #SQL + ' FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM #FrameChoices) T GROUP BY T.UserId'
PRINT #SQL
-- This generated SQL then can be executed by
EXEC(#SQL)
-- OR
EXEC SP_EXECUTESQL(#SQL)
-- Sample SQL generated from above query
SELECT UserId, MAX(CASE WHEN RowNumber =1 THEN Frame ELSE NULL END) AS Frame_1, MAX(CASE WHEN RowNumber =1 THEN Choice ELSE NULL END) AS Choice_1, MAX(CASE WHEN RowNumber =1 THEN Description ELSE NULL END) AS Description_1, MAX(CASE WHEN RowNumber =1 THEN [DateTime] ELSE NULL END) AS DateTime_1, MAX(CASE WHEN RowNumber =2 THEN Frame ELSE NULL END) AS Frame_2, MAX(CASE WHEN RowNumber =2 THEN Choice ELSE NULL END) AS Choice_2, MAX(CASE WHEN RowNumber =2 THEN Description ELSE NULL END) AS Description_2, MAX(CASE WHEN RowNumber =2 THEN [DateTime] ELSE NULL END) AS DateTime_2 FROM ( SELECT UserId,Frame,Choice,Description,[DateTime], ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [DateTime]) AS RowNumber FROM #FrameChoices) T GROUP BY T.UserId

What you want is the Pivot Table functionality of SQL Server
http://msdn.microsoft.com/en-us/library/ms177410(SQL.90).aspx

Related

Using pivot in SQL Server not returning desired output

I have two tables like this:
**tblTagDescription**
and **tblDataLog**
Now I want to show record of any specific group and in one there might be same group for multiple id in tbltagdescription. And id of tbltagdescription is foreign key for tblDataLog as TagDescID.
Here 'Group1' has 10 ID as from 1 to 10. and there might be multiple record for these ID (from 1 to 10) in tbldatalog. I want these ID from 1 to as columns. For this I used pivot:
DECLARE #COlsID NVARCHAR(MAX)
DECLARE #SQL NVARCHAR(MAX)
DECLARE #Group NVARCHAR(50) = 'Group1'
IF OBJECT_ID('tempdb..##MYTABLE') IS NOT NULL
DROP TABLE ##MYTABLE
SELECT
#COlsID = COALESCE(#ColsID + '],[','') + CONVERT(NVARCHAR(5), z.TagDescID)
FROM
(SELECT DISTINCT TOP 50 tblDataLog.TagDescID
FROM tblDataLog
INNER JOIN tblTagDescription ON tblDataLog.TagDescID = tblTagDescription.ID
ORDER BY tblDataLog.TagDescID) z
SET #COlsID='[' + #COlsID + ']'
SET #SQL='select [DATE],SHIFT, ' + #COlsID + ' into ##MYTABLE from ( select [Date], Value,
(CASE
WHEN ((DATEPART(hour,[DATE]))>6 and (DATEPART(hour,[DATE]))<14) THEN ''A''
WHEN ((DATEPART(hour,[DATE]))>=14 and (DATEPART(hour,[DATE]))<22) THEN ''B''
WHEN ((DATEPART(hour,[DATE]))>=22 or (DATEPART(hour,[DATE]))<6) THEN ''C''
END )AS SHIFT
from tblDataLog )d pivot(max(Value) for TagDescID in (' + #COlsID + ')) piv;'
EXEC (#SQL)
Now when I execute this statement, I get an error:
Invalid column name 'TagDescID'
but there is this column in tbldatalog. How to solve this query?
You need TagDescID column in subquery.
DECLARE #COlsID NVARCHAR(MAX) = ''
DECLARE #COlsAlias NVARCHAR(MAX) = ''
DECLARE #SQL NVARCHAR(MAX)
DECLARE #Group NVARCHAR(50) = 'Group1'
SELECT
#COlsID = #ColsID + ',' + z.TagDescID,
#COlsAlias = #COlsAlias + ',' + z.TagDescID + ' AS ' + z.ReportTag
FROM
(SELECT DISTINCT TOP 50 tblDataLog.TagDescID ID, QUOTENAME(CONVERT(NVARCHAR(5), tblDataLog.TagDescID )) TagDescID, QUOTENAME(tblTagDescription.ReportTag) ReportTag
FROM tblDataLog
INNER JOIN tblTagDescription ON tblDataLog.TagDescID = tblTagDescription.ID
ORDER BY tblDataLog.TagDescID
) z
SET #COlsID= STUFF(#COlsID,1,1,'')
SET #COlsAlias= STUFF(#COlsAlias,1,1,'')
SET #SQL='select [DATE],SHIFT, ' + #COlsAlias + ' into ##MYTABLE from ( select [Date], Value, TagDescID,
(CASE
WHEN ((DATEPART(hour,[DATE]))>6 and (DATEPART(hour,[DATE]))<14) THEN ''A''
WHEN ((DATEPART(hour,[DATE]))>=14 and (DATEPART(hour,[DATE]))<22) THEN ''B''
WHEN ((DATEPART(hour,[DATE]))>=22 or (DATEPART(hour,[DATE]))<6) THEN ''C''
END )AS SHIFT
from tblDataLog )d pivot(max(Value) for TagDescID in (' + #COlsID + ')) piv;'
EXEC (#SQL)

T-SQL dynamic row checking

I am trying to run a check on a table where, for each row, I want to see whether the column has a a null in it and add a 1 like here:
SELECT
((CASE WHEN col1 IS NULL THEN 1 ELSE 0 END)
+ (CASE WHEN col2 IS NULL THEN 1 ELSE 0 END)
+ (CASE WHEN col3 IS NULL THEN 1 ELSE 0 END)
...
...
+ (CASE WHEN col10 IS NULL THEN 1 ELSE 0 END)) AS sum_of_nulls
FROM table
WHERE Customer=some_cust_id'
This method does what its supposed to in a static way but is it possible to dynamically build the columns based on the table as opposed to writing out each case statement.
Many thanks!
Here's what I came up with
declare
#sql nvarchar(max),
#columns nvarchar(max),
#table nvarchar(128) = '<your table here>'
select
#columns = stuff((select '+case when ' + quotename(column_name) + ' is null then 1 else 0 end'
from information_schema.columns
where table_name = #table
order by ordinal_position
for xml path('')), 1, 1, ''),
#sql = 'select sum_of_nulls = ' + #columns + ', *
from dbo.' + quotename(#table)
exec sp_executesql #sql
You can slot in a where clause after the table name if you want also. Right now, it just returns for everything in the table.

Count number of NULL values in each column in SQL

I am trying to write a script that will show the number of non-null values in each column as well as the total number of rows in the table.
I have found a couple ways to do this:
SELECT sum(case my_column when null then 1 else 0) "Null Values",
sum(case my_column when null then 0 else 1) "Non-Null Values"
FROM my_table;
and
SELECT count(*) FROM my_table WHERE my_column IS NULL
UNION ALL
SELECT count(*) FROM my_table WHERE my_column IS NOT NULL
But these require me to type in each column name manually. Is there a way to perform this action for each column without listing them?
You should use execute:
DECLARE #t nvarchar(max)
SET #t = N'SELECT '
SELECT #t = #t + 'sum(case when ' + c.name + ' is null then 1 else 0 end) "Null Values for ' + c.name + '",
sum(case when ' + c.name + ' is null then 0 else 1 end) "Non-Null Values for ' + c.name + '",'
FROM sys.columns c
WHERE c.object_id = object_id('my_table');
SET #t = SUBSTRING(#t, 1, LEN(#t) - 1) + ' FROM my_table;'
EXEC sp_executesql #t
As Paolo said, but here is an example:
DECLARE #TableName VARCHAR(512) = 'invoiceTbl';
DECLARE #SQL VARCHAR(1024);
WITH SQLText AS (
SELECT
ROW_NUMBER() OVER (ORDER BY c.Name) AS RowNum,
'SELECT ''' + c.name + ''', SUM(CASE WHEN ' + c.Name + ' IS NULL THEN 1 ELSE 0 END) AS NullValues FROM ' + #TableName AS SQLRow
FROM
sys.tables t
INNER JOIN sys.columns c ON c.object_id = t.object_id
WHERE
t.name = #TableName),
Recur AS (
SELECT
RowNum,
CONVERT(VARCHAR(MAX), SQLRow) AS SQLRow
FROM
SQLText
WHERE
RowNum = 1
UNION ALL
SELECT
t.RowNum,
CONVERT(VARCHAR(MAX), r.SQLRow + ' UNION ALL ' + t.SQLRow)
FROM
SQLText t
INNER JOIN Recur r ON t.RowNum = r.RowNum + 1
)
SELECT #SQL = SQLRow FROM Recur WHERE RowNum = (SELECT MAX(RowNum) FROM Recur);
EXEC(#SQL);
may be this works
select count(case when Column1 is null then 1 end) as Column1NullCount,
count(case when Column2 is null then 1 end) as Column2NullCount,
count(case when Column3 is null then 1 end) as Column3NullCount
...
from My_Table
you can go with dynamic sql and sys tables.
depending on the version of sql you are using the syntax will change slightly but these are the steps:
- list the columns reading sys.columns and save the list in a temp table or table variable
- make a loop through that temp table and build the sql using the same logic you would apply manually
- execute the dynamic sql built on previous step with sp_executesql

Transpose Row to Column in SQL Server 2000

I am trying to convert rows into columns in SQL Server 2000. Although all rows converted into required columns but i unable to get the value converted into the respective columns.
My code is:
DROP TABLE prePivot1
DROP TABLE results1
CREATE TABLE prePivot1 (
[StudentId] uniqueidentifier
, [Sub_Abbr] Varchar(100)
, [Total_marks] MONEY
)
CREATE TABLE results1 (
[StudentId] uniqueidentifier
)
INSERT INTO prePivot1
SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'ENG', 55
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'MBEN', 90
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'ECO', 80
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'PSc', 45
UNION SELECT '{4FD7CBBA-1621-4102-B4A3-000BF92E2F6E}', 'PSY', 23
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'ENG', 90
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'ECO', 44
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'PSc', 45
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'BST', 23
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'ASS', 80
UNION SELECT '{AD288712-5C97-446B-8AFE-003FC845B56B}', 'PSY', 93
DECLARE #sql VARCHAR(8000)
DECLARE #pivot varchar(10)
DECLARE pivotCursor CURSOR LOCAL READ_ONLY FOR
SELECT DISTINCT
[Sub_abbr]
FROM
prePivot1
OPEN pivotCursor
FETCH NEXT FROM pivotCursor INTO #pivot
WHILE (##FETCH_STATUS = 0) BEGIN
SET #sql = '
ALTER TABLE results1 ADD [' + CAST(#pivot AS VARCHAR(10)) + '] INT'
EXEC (#sql)
FETCH NEXT FROM pivotCursor INTO #pivot
END
CLOSE pivotCursor
INSERT INTO results1 ([studentId])
SELECT DISTINCT [StudentId] FROM prePivot1
OPEN pivotCursor
FETCH NEXT FROM pivotCursor INTO #pivot
WHILE (##FETCH_STATUS = 0) BEGIN
SET #sql = '
UPDATE results1
SET
[' + CAST(#pivot AS VARCHAR(10)) + '] = pp.[total_marks]
FROM
prePivot1 pp
WHERE
pp.[total_marks] = ' + CAST(#pivot AS VARCHAR(10)) + '
AND pp.[studentId] = results1.[studentId]'
EXEC (#sql)
FETCH NEXT FROM pivotCursor INTO #pivot
END
CLOSE pivotCursor
DEALLOCATE pivotCursor
SELECT * FROM results1
Please help me how do i do to get the expected result.
Thanking you in advance.
There are a couple of things wrong with your predicate here:
pp.[total_marks] = ' + CAST(#pivot AS VARCHAR(10)) + '
You are filtering on the wrong column
You are not generating a proper string with the #pivot part.
This is what it looks like when you print out your dynamic sql string. Notice that it causes a join on prePivot1.total_marks column to results1.ECO column which is not what you're intending.
UPDATE
results1
SET
[ECO] = pp.[total_marks]
FROM
prePivot1 AS pp
WHERE
pp.[total_marks] = ECO
AND pp.[studentId] = results1.[studentId]
Corrected version (you also don't need to cast the variable):
pp.[Sub_Abbr] = ''' + #pivot + '''
A slightly less error prone solution would be to parameterize your dynamic sql:
-- Change #sql --> nvarchar(4000)
SET #sql = N'
UPDATE
results1
SET
' + QUOTENAME(#pivot) + N' = pp.[total_marks]
FROM
prePivot1 AS pp
WHERE
pp.[Sub_Abbr] = #Sub_Abbr
AND pp.[studentId] = results1.[studentId];';
EXEC sp_executesql
#stmt = #sql,
#params = N'#Sub_Abbr varchar(10)',
#Sub_Abbr = #pivot;
This is the general pattern I've used in sql2k to pivot just for reference:
(I'm assuming here that StudentId, Sub_Abbr is unique though the schema doesn't explicitly confirm this)
SELECT
[StudentId],
MAX(CASE WHEN [Sub_Abbr] = 'ASS' THEN [Total_marks] ELSE NULL END) AS [ASS],
MAX(CASE WHEN [Sub_Abbr] = 'BST' THEN [Total_marks] ELSE NULL END) AS [BST],
MAX(CASE WHEN [Sub_Abbr] = 'ECO' THEN [Total_marks] ELSE NULL END) AS [ECO],
MAX(CASE WHEN [Sub_Abbr] = 'ENG' THEN [Total_marks] ELSE NULL END) AS [ENG],
MAX(CASE WHEN [Sub_Abbr] = 'MBEN' THEN [Total_marks] ELSE NULL END) AS [MBEN],
MAX(CASE WHEN [Sub_Abbr] = 'PSc' THEN [Total_marks] ELSE NULL END) AS [PSc],
MAX(CASE WHEN [Sub_Abbr] = 'PSY' THEN [Total_marks] ELSE NULL END) AS [PSY]
FROM
[dbo].[prePivot1]
GROUP BY
[StudentId];

Multiple column values in a single row

I have table like this
ID Status
1 5
1 6
1 7
2 5
2 6
2 7
I need the result like below
ID col1 col2 col3
1 5 6 7
2 5 6 7
Please help me
SELECT ID,
MAX(CASE WHEN status = 5 THEN Status ELSE NULL END) col1,
MAX(CASE WHEN status = 6 THEN Status ELSE NULL END) col2,
MAX(CASE WHEN status = 7 THEN Status ELSE NULL END) col3
FROM tableNAME
GROUP BY ID
SQLFiddle Demo
using PIVOT
SELECT *
FROM (
SELECT ID, Status, CASE Status
WHEN 5 THEN 'Col1'
WHEN 6 THEN 'Col2'
WHEN 7 THEN 'Col3'
END Stat
FROM tableName
) src
PIVOT
(
MAX(Status)
FOR Stat IN ([Col1],[Col2],[Col3])
) pivotTbl
SQLFiddle Demo
Attempt for unknown count of destination columns
--Create table TESTx (id int,status int)
--insert into TESTx Values (1,5),(1,6),(1,7),(1,17),(2,5),(2,7),(2,8),(3,1),(3,5);
-
Declare #Tab Varchar(50)='##tmp' + Replace(Cast(newID() as Varchar(36)),'-','')
Declare #SQL Varchar(max)
Declare #Cols Varchar(max)
Declare #Renames Varchar(max)
Select #Cols ='Create Table ' + #Tab + '(ID int'
Select #Cols=#Cols + ',[Col'+ Cast(Status as varchar(10))+'] int'
from
(Select Distinct top 1000 Status
from
TESTx order by Status
) a
Select #Cols=#Cols +')'
Select #SQL= #Cols
+' Insert into '+#Tab +' (ID) Select Distinct ID from TESTx'
exec(#SQL)
Declare #Status int
DECLARE P_cursor CURSOR FOR
SELECT Distinct Status from TESTx
OPEN P_cursor
FETCH NEXT FROM P_cursor
INTO #Status
WHILE ##FETCH_STATUS = 0
BEGIN
Select #SQL='Update ' + #Tab + ' Set Col' + CAST(#Status as Varchar(10)) +'=' +Cast(#Status as Varchar(10))
+' from TESTx Where TESTx.ID=' + #Tab +'.ID and Testx.Status=' +Cast(#Status as Varchar(10))
Exec(#SQL)
FETCH NEXT FROM P_cursor
INTO #Status
END
CLOSE P_cursor
DEALLOCATE P_cursor
Select #SQL=' Select * from '+#Tab +' Drop Table ' + #Tab
Exec(#SQL)