Convert Rows into Dynamic columns using Pivot - sql

I have following information about real estate data in single table:
PropertyID
OwnerName
OwnershipDate
PropertyAddress
You can find sample data here
I want to pivot the results into desired output as follows
PropertyID OwnerName OwnershipDate OwnerName OwnershipDate
0121320100011 RIVERA VICTOR 2018-02-06 00:00:00.0000000 RIVERA RAQUEL 2018-02-06 00:00:00.0000000
I want the number of columns to be dynamic as per number of owners found against each PropertyID.
The efforts made so far are as bellow:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.OwnerName)
FROM owners_rec c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + ' from
(
select account,ownername
from owners_rec
) x
pivot
(
max(account)
for ownername in (' + #cols + ')
) p '
execute(#query)
Helping hands are always loved :)

Related

Summing multiple dynamically declared variables (fast)

I'm developing a program where I have multiple columns which I need to show the sum of to anEnd-user. These columns are assigned in the table ColumnTest in the column ColumnNames and their names can be changed by the user. Therefore I need to look up all the column names in ColumnTest\ColumnNames and afterwards sum all values regarding these columnnames from the outputtable.
I have previously used this script where I get all the columnnames in #cols like this [col1].[col2].[col3] and so on, but when I try to run the query I'm not able to sum these columns using '+ #cols + '. When I run this I get the following error: The SUM function requires 1 argument(s). Is there a viable option to do this procedure, without compromising the loading-time substantially?
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.ColumnNames)
FROM ColumnTest c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query =
'
SELECT
ID
,SUM('+ #cols + ')
FROM Output_table
GROUP BY
ID
'
execute(#query);
Try this,
DECLARE
#cols AS NVARCHAR(MAX)='',
#query AS NVARCHAR(MAX);
SELECT #cols += 'SUM('+ColumnNames+') as ['+ColumnNames+'],'
from
(
SELECT distinct ColumnNames FROM ColumnTest
)A
SELECT #cols=LEFT(#cols,LEN(#cols)-1)
set #query =
'
SELECT ID,'+ #cols + '
FROM Output_table
GROUP BY ID
'
execute(#query);
or if you want addition of all column values you can use below query
DECLARE #cols AS NVARCHAR(MAX)='',
#query AS NVARCHAR(MAX);
SELECT #cols += ''+ColumnNames+'+'
FROM
(
SELECT DISTINCT ColumnNames FROM ColumnTest
)A
SELECT #cols=LEFT(#cols,LEN(#cols)-1)
set #query =
'
SELECT ID,SUM('+ #cols + ')
FROM Output_table
GROUP BY ID
'
execute(#query);
You can not use comma separated like ','
You can use '+'
Try this
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct '+' + QUOTENAME(c.ColumnNames)
FROM ColumnTest c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query =
'
SELECT
ID
,SUM('+ #cols + ')
FROM Output_table
GROUP BY
ID
'
execute(#query);

Combine two pivot tables SQL Server

I am trying to cross join two pivot tables.
--First Pivot table query gets columns of drug_names and produces the row value
--of the drug_id.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(drug)
from _app_drugs
group by drug, drug_id,order_number
order by order_number
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select drug_id, drug
from _app_drugs
) x
pivot
(
max(drug_id)
for drug in (' + #cols + N')
) p'
exec sp_executesql #query;
--The second pivot table simply gets the signature_labels and displays the label name in the column and displays the label_id as the row value.
DECLARE #cols AS NVARCHAR(MAX),#scols as NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(signature_label)
from _app_signature_labels
WHERE _app_signature_labels.isactive=1
group by signature_label_id, signature_label,ordernumber
order by ordernumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select signature_label_id,signature_label
from _app_signature_labels
) x
pivot
(
max(signature_label_id)
for signature_label in (' + #cols + N')
) p'
exec sp_executesql #query;
Now I just need to know how to combine these two pivot tables as one table... they don't have a common field and don't need one.
Can anybody help me with this one?
Thank you
You can execute two separate dynamic SQL statements into two global temp tables and then combine the result, like this:
IF object_id('tempdb..##tmpResult1') IS NOT NULL
BEGIN
DROP TABLE ##tmpResult1
END
IF object_id('tempdb..##tmpResult2') IS NOT NULL
BEGIN
DROP TABLE ##tmpResult2
END
DECLARE #cols AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#query2 AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(drug)
from _app_drugs
group by drug, drug_id,order_number
order by order_number
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' INTO ##tmpResult1 from
(
select drug_id, drug
from _app_drugs
) x
pivot
(
max(drug_id)
for drug in (' + #cols + N')
) p'
exec sp_executesql #query;
--The second pivot table simply gets the signature_labels and displays the label name in the column and displays the label_id as the row value.
Select #cols2 = STUFF((SELECT ',' + QUOTENAME(signature_label)
from _app_signature_labels
WHERE _app_signature_labels.isactive=1
group by signature_label_id, signature_label,ordernumber
order by ordernumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query2 = N'SELECT ' + #cols2 + N' INTO ##tmpResult2 from
(
select signature_label_id,signature_label
from _app_signature_labels
) x
pivot
(
max(signature_label_id)
for signature_label in (' + #cols2 + N')
) p'
exec sp_executesql #query2;
SELECT * FROM ##tmpResult1 t1
INNER JOIN ##tmpResult2 t2 ON t1.ordernumber = t2.ordernumber
This is also a way to address this error when doing a large PIVOT query: Internal error: An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.

record in pivot format in sql server

we are using sql server 2008 and data in below format.
and i want to above record in below pivot format.
please help.
select * from PivotEx
pivot
(
avg(avg)
for city in ( [Mumbai] ,[Ahmedabad],[Raikot])
) piv;
To pass the values dynamically in pivot
Declare #cols nvarchar(max)
Declare #query nvarchar(max)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(city)
FROM PivotEx
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = ' select * from PivotEx
pivot
(
avg(avg)
for city in (' + #cols + ')
) p '
execute(#query)

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)

SQL Server 2012 Pivot

I have pivot solution that works fine but SQL server won't let me save it since it contains queries. Here is my original table:
ApplicationID ApplicationName ContactType Email
1 App1 type1 myemail#gmail.com
1 App1 type2 someemail#yahoo.com
2 App2 type1 email#email.com
2 App2 type3 someemail#yahoo.com
3 App3 type2 me#yahoo.com
Desired table:
ApplicationID ApplicationName Type1 Type2 Type3
1 App1 myemail#gmail.com
1 App1 someemail#yahoo.com
2 App2 email#email.com
& so on.... but i want dynamic pivoting meaning if there is new contactType added later on it just gets added to the view. Here is the query that I have which I'm unable to save as view:
DECLARE #cols AS NVARCHAR(MAX),
#colsNull AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(contactType)
from ApplicationContact
group by contactType
order by contactType
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsNull = STUFF((SELECT ', coalesce(' + QUOTENAME(contactType)+', '''') as '+QUOTENAME(contactType)
from ApplicationContact
group by contactType
order by contactType
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ApplicationID, ApplicationName, ' + #colsNull + '
from
(
select ApplicationID, ApplicationName, contactType, Email flag
from ApplicationContact
) x
pivot
(
max(flag)
for contactType in (' + #cols + ')
) p '
execute(#query)
My error is: Incorrect syntax near the keyword 'DECLARE'
Please help. Thanks
Generally, views are single select statements used to join and/or filter data from tables, TVFs, or stored procedures. As a result the user can't declare variables in a view.
I'd suggest placing this script into a SP where you can declare variables and then calling the SP in the view.
Hope that helps.
If you just want the pivoted result, you can use the below queries.
Declare columns for pivot
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ContactType + ']', '[' + ContactType + ']')
FROM
(
SELECT DISTINCT ContactType
FROM ApplicationContact
) PV
ORDER BY ContactType
Now you need to apply ROW_NUMBER to display Type 1, Type 2 etc in different rows.
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT ApplicationID , ApplicationName, ' + #cols + '
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY ApplicationID ORDER BY (SELECT 0))RNO,
ApplicationID , ApplicationName, ContactType, Email
FROM ApplicationContact
) x
PIVOT
(
MIN(Email)
FOR ContactType IN (' + #cols + ')
) p
ORDER BY ApplicationID;'
EXEC SP_EXECUTESQL #query
Click here to view result
As suggested here, you can use dynamic SQL in a view with SELECT * FROM OPENQUERY(...), but it's not that great of a solution. I would recommend using a proc as an alternative to a view.
EDIT - Adding my comment above to my answer:
If your data doesn't have to be real-time, you could use a job to execute your query to populate a table that you can use in place of the view. It can probably be run quite often since it doesn't seem to be that heavy of a query.