SQL Server 2012 Pivot - sql

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.

Related

Convert Rows into Dynamic columns using Pivot

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 :)

How to Count attendance hours on each day by user on SQL Server

I am new here.
I have the fallowing data on a table:
And I need to get the fallowing result:
I am using the fallowing SQL query:
SQL Query
DECLARE #sql AS NVARCHAR(MAX)=''
DECLARE #cols AS NVARCHAR(MAX)=''
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Date)
FROM vRecords
ORDER BY ',' + QUOTENAME(Date)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #sql = N'
SELECT EmpID, Name, ' + #cols + '
FROM (
select EmpID,Name,Date,Time
from vRecords
) a
PIVOT(COUNT(Time) FOR Date IN (' + #cols + ')) p'
EXECUTE(#sql)
What I need to accomplish is to know how many TIMES the user have a record on each DATE
But I am getting wrong result:
What am I doing wrong?
Sorry for all the links but because I am new I can't embed images.
I figured the issue.
All the problem was related to date format.
The columns were been generated with this format 2018-09-12 and the data was on this format 12/09/2018.
Any way, thanks for the comments.

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: case/if else -select and apply function only if present in table

I have the following dynamic query that creates a pivoted table for each account_id against the products using an UDF. I need to add spaces after the UDF is executed depending up the account_id being matched to the specific tables. This works perfectly fine, and returns the 2nd table in the image, I just want to add some condition where it checks for account id's present in other tables and then adds spaces to output from the UDF eg- the account id in the pivot matches the id present in test_rev then 2 spaces if the account_id in the pivot matches the id present in test_oncontract then 3 spaces so on
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.A_NAME)
FROM TEST_11 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT account_id, ' + #cols + ' INTO TEST_DETAIL from
(
select account_id
, dbo.make_table(apple,ball,cat,dog) AS newvalue
,a_name
from test_sample
) x
pivot
(
MAX(newvalue)
for a_name in (' + #cols + ')
) p '
execute(#query)
Image below shows how make_table udf converts the 1st table into 2nd just picking up the initials from each column name from the 1st table
I was able to call my function and add the required spaces withing the select.
But the case statement just executes the first condition and I cant get the records from the other tables. How can I implement if conditions instead of the case statements to to get data depending on all four conditions. Below is the code I am currently using:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.a_name)
FROM CRS_PRODLINE c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT account_id, ' + #cols + ' INTO TEST_DETAIL from
(select account_id,
(case
when exists (select account_id from [dbo].[TEST_R6])
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(1) + ''rr''
when exists (select account_id from tbl_noR6)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(2) + ''cc''
when exists (select account_id from tbl_acct)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(3) + ''pp''
when exists (select account_id from test_NA)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(4) + ''no''
end) as newvalue,
a_name
from CRS_PRODLINE
) x
pivot
(
MAX(newvalue)
for a_name in (' + #cols + ')
) p '
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