Convert Columns values into Rows in SQL 2008 - sql

It would be great if you can help me to convert Column into Rows in SQL Table.
Let say, I have 3 columns called:
Employee_ID
Shift_Date
Shift_ID
Currently it come up like this:
Table Like this
I want to appear like that as the result -
Result Table
But I want value in it, can you guys please help. Thanks.
This is a query I wrote but still error:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(shift_date)
from dbo.tbl_Multi_Shift_Employee WHERE Shift_Date BETWEEN CONVERT(DATE, '01/02/2018 00:00:00',103) AND CONVERT(DATE, '28/02/2018 00:00:00',103)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Employee_ID, total, Department_ID, shift_id, ' + #cols + ' from
(
select count(*) over(partition by t.Employee_ID) total,
s.Department_ID,
t.Employee_ID,
t.shift_id
from dbo.tbl_Multi_Shift_Employee t
inner join dbo.tbl_department s
on t.Department_ID = s.Department_ID
) x
pivot
(
count(shift_id)
for shift_id in (' + #cols + ')
) p '
PRINT #query
execute(#query)

First you must to remove shift_id from primary select because is used as pivot.
Second, change shift_id with shift_date that is the correct column you are using as pivot columns.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(shift_date)
from dbo.tbl_Multi_Shift_Employee WHERE Shift_Date BETWEEN CONVERT(DATE, '01/02/2018 00:00:00',103) AND CONVERT(DATE, '28/02/2018 00:00:00',103)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Employee_ID, total, Department_ID, ' + #cols + ' from
(
select count(*) over(partition by t.Employee_ID) total,
s.Department_ID,
t.Employee_ID,
t.shift_id,
t.shift_date
from dbo.tbl_Multi_Shift_Employee t
inner join dbo.tbl_department s
on t.Department_ID = s.Department_ID
) x
pivot
(
count(shift_id)
for shift_date in (' + #cols + ')
) p '
PRINT #query
execute(#query)

Related

How to make SQL Pivot display more than one row

I was able to display every row in column using pivot however when there are multiple values, it displays only one of the row values. My suspicion lies on the MAX function in the for loop, however, have not been able to find a successful replacement.
I've tried other SQL functions.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(Provincia)
FROM Codigos_Postales
GROUP BY Provincia
ORDER BY Provincia
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT Poblacion,' + #cols + N' from
(
select * from Codigos_Postales
) x
pivot
(
MAX(Codigo_Postal)
for Provincia in (' + #cols + N')
) p ORDER BY Poblacion ASC'
EXEC sp_executesql #query;
Table I'm trying to pivot:
Result:
Expected Result:
If I understand corerctly, adding ROW_NUMBER to your source data will do the trick. The sample PIVOT script will be as below. Just ignore the RN column from your final output, that's it.
SET #query =
N'SELECT Poblacion,' + #cols + N' from
(
SELECT
ROW_NUMBER() OVER (ORDER BY Provincia) RN,
*
FROM Codigos_Postales
) x
PIVOT
(
MAX(Codigo_Postal)
FOR Provincia IN (' + #cols + N')
) p ORDER BY Poblacion ASC'

How to display columns as rows in a SQL query?

I'm trying to display exam results form simple database containing two tables tblStudents and tblExamResults.
tblstudents contains student ID and Full_Name columns
In tblexamResults columns are Student_id, Subject and Marks.
as in below Picture
1- Currently I am displaying Student results using this query
SELECT tblStudents.Full_Name, tblExamResults.Subject, tblExamResults.Marks
FROM tblExamResults INNER JOIN
tblStudents ON tblExamResults.Student_id = tblStudents.Student_ID
order by tblStudents.Full_Name
2 - And results looks like in the following picture:
3 - But what I want is to display each subject as row and get result of each subject below it
So that each student's result is displayed in the same row:
Student_Name sub1_result sub2_Result sub3_Result
Like in the following picture (Excel screenshot)
So:
How I can display data in that format?
Is that possible in SQL Server?
select fullname,[english] english, [history] history, [physics] physics
from
(
select fullname,subject,marks
from (yourquery)
) src
pivot
(
max(marks)
for subject in ([english], [history], [physics])
) piv;
or
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.subject)
FROM (yourquery) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT fullname, ' + #cols + ' from
(
select fullname,subject,marks
from (your query)
) x
pivot
(
max(marks)
for subject in (' + #cols + ')
) p '
execute(#query)
fullname english history physics
a 85 70 60
i 60 100 89
s 90 90 99
Finally I've used next part of #Chanukya Answer with little Changes
in that Answer i was getting error at line 5 becouse of parentheses in FROM (yourquery) c
Declare #query nvarchar(max);
DECLARE #cols AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.subject)
FROM tblExamResults c ' parentheses Removed from (tblExamResults) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
print(#cols)
set #query = '
SELECT *
FROM (
SELECT tblStudents.Full_Name, tblExamResults.Subject, tblExamResults.Marks
FROM tblExamResults INNER JOIN
tblStudents ON tblExamResults.Student_id = tblStudents.Student_ID
) as s
PIVOT
(
sum(marks) FOR subject IN ('+ #cols +')
)AS pvt'
;
execute(#query)

The column '638' was specified multiple times for 'PVT'. Pivot

I've the following SQL Query
Select Product_Id, [riy] AS [riy],
[eas] AS [eas]
FROM
(SELECT Product_Id, Store_Name, Quantity
FROM [Product_Stock] INNER JOIN Store on Store.Id = [Product_Stock].Stock_Id where Product_Id = 435) ps
PIVOT
(
SUM(Quantity)
FOR Store_Name IN
([riy],[EAST WAREHOUSE - eas])
) AS pvt
it gives the expected result.Giving me total quantity for locations riy and eas.
However, I want to dynamically get the Store names instead of manually specifying them.
this is what I've done.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME([Product_Id])
FROM [Product_Stock]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #query =
'SELECT Product_Id FROM
(SELECT Product_Id, Store_Name, Quantity
FROM [Product_Stock] INNER JOIN Store on Store.Id = [Product_Stock].Stock_Id where Product_Id = 435) PS
PIVOT
(
SUM(Quantity)
FOR Store_Name in (' + #cols + ')
) AS PVT'
EXEC SP_EXECUTESQL #query
This gives me an error saying The column '638' was specified multiple times for 'PVT'.
How can i solve this problem?
Without knowing your actual data this is a blind flight, but I think you have two issues:
You must use DISTINCT to get each value only once
You are not concatenating the stores names but the IDs of your products
Try this
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME([Store_Name])
FROM [Product_Stock]
INNER JOIN Store on Store.Id = [Product_Stock].Stock_Id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Just make sure the cols are DISTINCT
... STUFF((SELECT DISTINCT ','...
Thanks #Shnugo for pushing me in the right direction. Here's the query I finally ended up using.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME([Store].Store_Name)
FROM [Store] INNER JOIN Product_Stock ON Product_Stock.Stock_Id = Store.Id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #query =
'SELECT Product_Id , ' + #cols + ' from
(SELECT Product_Id, Store_Name, Quantity
FROM [Product_Stock] INNER JOIN Store on Store.Id = [Product_Stock].Stock_Id WHERE Product_Stock.product_id = 435 ) PS
PIVOT
(
SUM(Quantity)
FOR Store_Name in (' + #cols + ')
) AS PVT'
EXEC SP_EXECUTESQL #query

Sort Rows of Dynamic Pivot Table

I have the following query to dynamically pivot some row information:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT ',' + QUOTENAME(convert(char(50), ScheduleEndTime, 120))
FROM metersNotRead
group by ScheduleEndTime
order by ScheduleEndTime DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ScheduleName, MeterID, CurrentGK,
' + #cols + ' from
(
select ScheduleName, MeterID, CurrentGK, ScheduleEndTime, ''Y'' flag
from metersNotRead
) x
pivot
(
max(flag)
for ScheduleEndTime in (' + #cols + ')
) p
order by ' + #cols +' DESC
'
execute(#query)
It gives me the correct results, but I am wondering how I can sort the rows by the first dynamic column, then the second, and so on, until all dynamic columns have been ordered by.
The results I have now are like this:
ScheduleName MeterID CurrentGK FirstDynamicCol SecondDynamicCol ETC
textName1 exampleID1 -- NULL Y
taxtName2 exampleID2 -- Y NULL
I want them to be like this:
ScheduleName MeterID CurrentGK FirstDynamicCol SecondDynamicCol ETC
textName2 exampleID2 -- Y NULL
taxtName1 exampleID1 -- NULL Y
Try this, put your first column name in its own variable, and order by that only.
DECLARE #cols AS NVARCHAR(MAX), #orderby NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #orderby = STUFF((SELECT ',' + QUOTENAME(convert(char(50), ScheduleEndTime, 120)) + ' desc'
FROM metersNotRead
group by ScheduleEndTime
order by ScheduleEndTime DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #cols = STUFF((SELECT ',' + QUOTENAME(convert(char(50), ScheduleEndTime, 120))
FROM metersNotRead
group by ScheduleEndTime
order by ScheduleEndTime DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ScheduleName, MeterID, CurrentGK,
' + #cols + ' from
(
select ScheduleName, MeterID, CurrentGK, ScheduleEndTime, ''Y'' flag
from metersNotRead
) x
pivot
(
max(flag)
for ScheduleEndTime in (' + #cols + ')
) p
order by ' + #orderby
execute(#query)

while converting column to row not able to fetch value from another table automatically

select *
from (
select vtid, convert(date, dtime) as Date from Transaction_tbl where locid = 5
) as vt
pivot (
count(vtid)
for vtid in (select vtid from VType_tbl)
) as pvt
while executing this query am getting error
Incorrect syntax near the keyword 'select'." and Incorrect syntax near
')'.
actually I have one more table,name= Vtype_table , How Can I load all vtid from vtype table in this query? I want to get output depend upon vtid.
Any help greatly appreciated.
Your PIVOT syntax is correct except you are using a SELECT statement inside your PIVOT.
You cannot use a SELECT statement inside the PIVOT IN clause to select column headers. It is required that the columns for the IN clause be known prior to executing the query.
If you are looking to generate a dynamic list of vtid values, then you will need to use dynamic SQL to get the result and the syntax will be similar to the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vtid)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select vtid, convert(date, dtime) as Date
from Transaction_tbl
where locid = 5
) d
pivot
(
count(vtid)
for vtid in (' + #cols + ')
) p '
execute(#query);
Edit, if you want the type names to appear then you should be able to use the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vt_name)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select v.vt_name, convert(date, dtime) as Date
from Transaction_tbl t
inner join VType_tbl v
on t.vtid = v.vtid
where locid = 5
) d
pivot
(
count(vt_name)
for vt_name in (' + #cols + ')
) p '
execute(#query)
Note: I am guessing on the column name for VType_tbl