Show value of particular column as Header in SQL Server - sql

I am creating a web app in which I have a requirement where I want to display a column value as a header
Example
SELECT Name, Leave
FROM tblUser
INNER JOIN tblLeaveMaster ON tblUser.EmployeeID = tblLeaveMaster.EmployeeID
From that query, I get these results:
Name Leave
---------------
Test1 5
Test2 10
test3 2
Now I want to get these values as
Test1 Test2 Test3
-----------------
5 10 2
How can I achieve this?

You can try using pivot
select pv.* from
(SELECT Name,Leave
FROM tblUser INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID
)X
pivot
(max(leave) for name in ([Test1],[Test2],[Test3])) as pv
For Dynamic PIVOT
declare #sql varchar(max)='',#col_list varchar(8000)=''
set #col_list = (select distinct quotename([Name])+',' from (SELECT Name,Leave
FROM tblUser INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID
)X
for xml path(''))
set #col_list = left (#col_list,len(#col_list)-1)
set #sql = 'select '+#col_list+' from
(SELECT Name,Leave
FROM tblUser INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID
)X
pivot (max([Leave]) for [Name] in ('+#col_list+'))pv'
exec(#sql)

try by using case when
select max( case when name='Test1' then Leave end) as test1,
max( case when name='Test2' then Leave end) as test2,
max( case when name='Test3' then Leave end) as test3 from
tblUser INNER JOIN tblLeaveMaster
ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID

You can try to use condition aggregate function. CASE WHEN with MAX or MIN
SELECT
MAX(CASE WHEN Name = 'Test1' THEN Leave END) Test1,
MAX(CASE WHEN Name = 'Test2' THEN Leave END) Test2,
MAX(CASE WHEN Name = 'Test3' THEN Leave END) Test3
FROM tblUser
INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID
EDIT
If your column want to create dynamic you can try to use Dynamic PIVOT
create your SQL statement and make condition aggregate function by connect SQL string. then use execute it Dynamically.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ', MAX(CASE WHEN Name = ''' + Name+''' THEN Leave END) ' + QUOTENAME(Name)
FROM tblUser
INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query= 'SELECT '+ #cols+'
FROM tblUser
INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID'
execute(#query)
sqlfiddle

You can find your result from the query as shown below. Here I have taken your query output in a temporary table.
Create table #finalData(ColName Varchar(30), Leave INT)
INSERT INTO #finalData Values('Test1', 5),('Test2', 10),('Test3', 2)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.ColName)
FROM #finalData c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + ' from
(
select ColName
, Leave
from #finalData
) x
pivot
(
max(Leave)
for ColName in (' + #cols + ')
) p '
execute(#query)
DROP TABLE #finalData
Hope this will help you.
The output is as shown below
Test1 Test2 Test3
5 10 2

select pv.* from
(SELECT Name,Leave
FROM tblUser INNER JOIN tblLeaveMaster ON tblUser.EmployeeID=tblLeaveMaster.EmployeeID
)X
pivot
(max(leave) for name in ([Test1],[Test2],[Test3])) as pv
Note:- this work for me but how to use where condition base on dropdown list selected value.
eg: if wants to show only 2020 and not 2019.

Related

Restriction to use DECLARE in a SQL view

I have a sql query that I need to put into a view. I have it working as a stored procedure but my requirement is for it to be a View. This means I cant declare dynamic SQL as I have done in my stored procedure.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(t.Data_Term)
from [UD_FldValues] t
inner join Surgery p
on t.Ud_Form_Id = p.Ud_Form_Id where t.Data_term!=''
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
set #query = 'SELECT Tran_Id,Section_Id,SubSection_Id,R_Id,Hospital_Id,Surgeon_Id,Procedure_ICD,Procedure_Details,DtSurgery_TimeIn,DtSurgery_TimeOut,Intra_oper_compl_Id, p.Discharge_Date,Discharge_Status_Id,Entered_By,Entered_Date,p.Status,p.Ud_Form_Id,p.Complication_ICD,p.Complication_Name, Procedure_Name, ' + #cols + ' from
(
select t.Tran_Id
, t.[R_Id]
, p.Ud_Form_Id
,p.Procedure_Name
,p.Section_Id
,p.SubSection_Id
,p.Hospital_Id
,p.Surgeon_Id
,p.Procedure_ICD
,p.Procedure_Details
,p.DtSurgery_TimeIn
,p.DtSurgery_TimeOut
,p.Intra_oper_compl_Id
,p.Discharge_Date
,p.Discharge_Status_Id
,p.Entered_By,
p.Entered_Date
,p.Status
,p.Complication_ICD
,p.[Complication_Name]
, case when (t.Data_Type=''Text'') THEN t.Text_Value Else Convert(varchar(MAx),Num_Value) END as txtvl
,t.Data_term
from Surgery p
left outer join [UD_FldValues] t
on t.Ud_Form_Id = p.Ud_Form_Id and t.Tran_Id=p.Surgery_Id
left outer join UD_Formmap fm ON fm.Ud_Form_Id = p.Ud_Form_Id
where fm.module_id = 1
) x
pivot
(
min(txtvl)
for Data_Term in (' + #cols + ')
) p '
exec(#query)
Please help me find an alternate way, but not store procedures. I need it in view
for a view it needs to be a single select statement,
your #cols statement returns a list of columns, this is used twice within your main select statement. so replacing #cols in your main query with the query that populates this should work.
set #query and then exec(#query) isnt necessary either so you just have to tidy up and make sure the right number of brackets are in place.
and it should look something like this.
SELECT Tran_Id
,Section_Id
,SubSection_Id
,R_Id,Hospital_Id
,Surgeon_Id,Procedure_ICD
,Procedure_Details
,DtSurgery_TimeIn
,DtSurgery_TimeOut
,Intra_oper_compl_Id
,p.Discharge_Date
,Discharge_Status_Id
,Entered_By,Entered_Date
,p.Status,p.Ud_Form_Id
,p.Complication_ICD
,p.Complication_Name
,Procedure_Name,
(select STUFF((SELECT distinct ',' + QUOTENAME(t.Data_Term)
from [UD_FldValues] t
inner join Surgery p
on t.Ud_Form_Id = p.Ud_Form_Id where t.Data_term!=''
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');))
from
(
select t.Tran_Id
, t.[R_Id]
, p.Ud_Form_Id
,p.Procedure_Name
,p.Section_Id
,p.SubSection_Id
,p.Hospital_Id
,p.Surgeon_Id
,p.Procedure_ICD
,p.Procedure_Details
,p.DtSurgery_TimeIn
,p.DtSurgery_TimeOut
,p.Intra_oper_compl_Id
,p.Discharge_Date
,p.Discharge_Status_Id
,p.Entered_By,
p.Entered_Date
,p.Status
,p.Complication_ICD
,p.[Complication_Name]
, case when (t.Data_Type=''Text'') THEN t.Text_Value Else Convert(varchar(MAx),Num_Value) END as txtvl
,t.Data_term
from Surgery p
left outer join [UD_FldValues] t
on t.Ud_Form_Id = p.Ud_Form_Id and t.Tran_Id=p.Surgery_Id
left outer join UD_Formmap fm ON fm.Ud_Form_Id = p.Ud_Form_Id
where fm.module_id = 1
) x
pivot
(
min(txtvl)
for Data_Term in (
select STUFF((SELECT distinct ',' + QUOTENAME(t.Data_Term)
from [UD_FldValues] t
inner join Surgery p
on t.Ud_Form_Id = p.Ud_Form_Id where t.Data_term!=''
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');)
) p

Can I pivot dynamic table with no group by in SQL Server

This is my data in table (left join from field table and value table)
This is my expected result table after use pivot function
Thanks for help ^___^
I suggest you to use dynamic SQL as fieldnames number may very in future:
DECLARE #columns nvarchar(max),
#sql nvarchar(max)
SELECT #columns = COALESCE(#columns,'') + ',' + QUOTENAME(c.fieldname)
FROM [Columns] c
ORDER BY c.cid
SELECT #sql = N'
SELECT *
FROM (
SELECT v.[row],
c.fieldname,
v.fieldvalue
FROM [Values] v
INNER JOIN [Columns] c
ON v.cid = c.cid
) t
PIVOT (
MAX(fieldvalue) FOR fieldname IN ('+STUFF(#columns,1,1,'')+')
) pvt'
EXEC sp_executesql #sql
Will output:
row FirstName LastName Email Phone
1 Arnun Saelim Arnun.s#outlook.com 0922743838
2 Micheal Saelim Micheal#gmail.com 0886195353
I'm not sure why group by got into your mind, but here is a working example of what you are trying to achieve.
select * into #temp from
( values
(1,'A','AV'),
(1,'B','BV'),
(1,'C','CV'),
(2,'A','AV'),
(2,'B','BV'),
(2,'C','CV'))
as t(row, FieldName, FieldValue)
select *
from #temp
PIVOT
(MAX(FieldValue) FOR FieldName in ([A],[B],[C])) as pvt
Does that work for you?

Combine Static Columns with Dynamic Columns in SQL SERVER 2008

I have a table SchoolStudent with three columns and the following values
Now, for a student we can have dynamic columns which are stored in a table with values as:
I want a query where i can club static fields as well as dynamic fields in a single SQL Query. I tried using Pivot but was not successful. Please suggest on how to accomplish this. I am basically doing it so that on frontend i have one resultset which can be searched thru.
So query should be:
Select
StudentID, FirstName, Address, MotherName,
MotherEmail, MotherOccupation, Mother Salary,
FacebookProfileName, VehicleRegNo
from SchoolStudent
Inner Join
(Logic to convert rows to columns)
Since you have dynamic columns, then you will need to use dynamic SQL to generate the result that you want. This query will generate the list of columns in the second table and PIVOT them to then be joined to the SchoolStudent to get the other columns:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(DynamicColumnName)
from StudentDetails
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = '
select s.studentid,
s.firstname,
s.address,
d.*
from SchoolStudent s
inner join
(
SELECT studentId,' + #cols + '
from
(
select studentId, dynamiccolumnname,
dynamiccolumnvalue
from StudentDetails
) x
pivot
(
max(dynamiccolumnvalue)
for dynamiccolumnname in (' + #cols + ')
) p
) d
on s.StudentId = d.StudentId'
execute(#query);
See SQL Fiddle with Demo. This query gives the result:
| STUDENTID | FIRSTNAME | ADDRESS | FACEBOOK PROFILE NAME | MOTHER EMAIL | MOTHER NAME | MOTHER OCCUPATION | MOTHER SALARY | VEHICLE REG NO |
-----------------------------------------------------------------------------------------------------------------------------------------------
| 4 | admin | efewfwfew | ross | ram#ram.com | ram#ram.com | ram#ram.com | ram#ram.com | UP 14 as |
You could use sub query format like this:
SELECT t1.StudentID,
t1.FirstName,
t1.Address,
(SELECT t2.DynamicColumnValue FROM table2 t2 WHERE t2.StudentID = t1.StudentID AND t2.DynamicColumnName = 'Mother Name') AS 'MotherName',
(SELECT t2.DynamicColumnValue FROM table2 t2 WHERE t2.StudentID = t1.StudentID AND t2.DynamicColumnName = 'Mother Email') AS 'MotherEmail'
FROM Table1 t1
or you could use inner join format like this:
SELECT t1.StudentID,
t1.FirstName,
t1.Address,
t2.DynamicColumnValue AS 'MotherName'
t3.DynamicColumnValue AS 'MotherEmail'
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.StudentID = t2.StudentID AND t2.DynamicColumnName = 'Mother Name'
INNER JOIN Table2 t3 ON t1.StudentID = t3.StudentID AND t2.DynamicColumnName = 'Mother Email'
With some dynamic sql, you can do this:
DECLARE #cols NVARCHAR(2000)
SELECT #cols = STUFF((SELECT DISTINCT '],[' + DynamicColumnName FROM DynamicValues ORDER BY '],[' + DynamicColumnName FOR XML PATH('')), 1, 2, '') + ']'
DECLARE #query NVARCHAR(4000);
SET #query = N'select s.StudentID, s.FirstName, s.Address,'+#cols+' from SchoolStudent s
join
(
select * from DynamicValues
pivot (Max(DynamicColumnValue) for DynamicColumnName in ('+#cols+')) as pvt
) as b on b.StudentID=s.StudentID'
EXECUTE(#query)

T:SQL: select values from rows as columns

I have a table for Profiles stores profile properties values in row style, ex:
[ProfileID] [PropertyDefinitionID] [PropertyValue]
1 6 Jone
1 7 Smith
1 8 Mr
1 3 50000
and another table for property definitions :
[PropertyDefinitionID] [PropertyName]
6 FirstName
7 LastName
8 Prefix
3 Salary
How to use PIVOT or any other way to show it in this way:
[ProfileID] [FirstName] [LastName] [Salary]
1 Jone Smith 5000
It's easy to do this without PIVOT keyword, just by grouping
select
P.ProfileID,
min(case when PD.PropertyName = 'FirstName' then P.PropertyValue else null end) as FirstName,
min(case when PD.PropertyName = 'LastName' then P.PropertyValue else null end) as LastName,
min(case when PD.PropertyName = 'Salary' then P.PropertyValue else null end) as Salary
from Profiles as P
left outer join PropertyDefinitions as PD on PD.PropertyDefinitionID = P.PropertyDefinitionID
group by P.ProfileID
you can also do this with PIVOT keyword
select
*
from
(
select P.ProfileID, P.PropertyValue, PD.PropertyName
from Profiles as P
left outer join PropertyDefinitions as PD on PD.PropertyDefinitionID = P.PropertyDefinitionID
) as P
pivot
(
min(P.PropertyValue)
for P.PropertyName in ([FirstName], [LastName], [Salary])
) as PIV
UPDATE: For dynamic number of properties - take a look at Increment value in SQL SELECT statement
It looks like you might have an unknown number of PropertyName's that you need to turn into columns. If that is the case, then you can use dynamic sql to generate the result:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(PropertyName)
from propertydefinitions
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT profileid, ' + #cols + ' from
(
select p.profileid,
p.propertyvalue,
d.propertyname
from profiles p
left join propertydefinitions d
on p.PropertyDefinitionID = d.PropertyDefinitionID
) x
pivot
(
max(propertyvalue)
for propertyname in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo.

SQL Pivot table returning NULL for non-existent child table values

I have a typical RDMS setup where records in a main table can have optional records in a related table via a M2M join. I'm trying to PIVOT this data but in cases where there is no relation I want to return a default value. The join I have below is returning NULL.
select *
from
(
SELECT s.Biz_Name, la.Name AS Association, ISNULL(i.Location, 'Default') as Location
FROM dbo.ShopAssociations sa
INNER JOIN dbo.LookupAssociations la
ON sa.AssociationID = la.AssociationID
RIGHT JOIN dbo.Basic_Shop_Info s
ON sa.ShopID = s.ShopID
INNER JOIN dbo.Images i
ON la.ImageID = i.ImageID
) DataTable
PIVOT
(
min(Location)
for association in
([OnCall],[OCGuy],[ASCLogo],[ASC_OtherSt],[ASE],[AASP],[AASP_PA],
[ASE_BlueSeal],[AAA],[AAA-B],[ASA],[ATRA],[ICAR],[CAA],[ACDelco],
[Cert],[ASC],[BBB],[Goodyear],[Limos],[RVs],[Bosch],[NARSA],
[DiscTire],[BigO],[Tires],[Firestone],[ASCCA],[JustTires],[ASE_Blue])
) PivotTable
The output looks like this:
BizName OnCall OCGuy ASCLogo ASC_OtherSt ASE ...
"Wonderful Biz" somevalue somevalue NULL somevalue NULL
What I am trying to achieve is if a child record doesn't exist in INNER JOIN from Basic_Shop_Info to ShopAssociations that we get "Default" instead of NULL. I've tried ISNULL(), Coalesce() and even a CASE statement, all with the same results.
Based on your comment it sounds like you found a solution. I am only answering this to provide a suggestion based on the fact you are pivoting so many columns and they are all hard-coded. You can use dynamic SQL for a PIVOT and your query would look something like this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsPivot AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Name)
from dbo.LookupAssociations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsPivot = STUFF((SELECT distinct ', IsNull(' + QUOTENAME(Name) +', ''Default'')'
from dbo.LookupAssociations
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Bizname, ' + #colsPivot + ' from
(
SELECT s.Biz_Name, la.Name AS Association, ISNULL(i.Location, ''Default'') as Location
FROM dbo.ShopAssociations sa
INNER JOIN dbo.LookupAssociations la
ON sa.AssociationID = la.AssociationID
RIGHT JOIN dbo.Basic_Shop_Info s
ON sa.ShopID = s.ShopID
INNER JOIN dbo.Images i
ON la.ImageID = i.ImageID
) x
pivot
(
min(Location)
for association in (' + #cols + ')
) p
'
execute(#query)
The value #colsPivot is adding the IsNull() around each of you columns so you can put in place the Default value. But this should provide the same result as your original query where everything was hard-coded.
This will get the list of columns at run-time so then you do not have to hard-code anything and it will accept new values without having to change the query.
I got this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(c.col+cast(rn as varchar(10)))
from
(
select row_number() over(partition by person_nbr
order by person_nbr,first_name, last_name, medication_name) rn
from TA_PIVOT
) d
cross apply
(
select 'diag' col, 1 sort
) c
group by col, rn, sort
order by rn, sort
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT person_nbr, first_name, last_name,medication_name,' + #cols + '
from
(
select person_nbr,first_name,last_name,medication_name,
col+cast(rn as varchar(10)) col,
value
from
(
-- when you perform an unpivot the datatypes have to be the same.
-- you might have to cast the datatypes in this query
select person_nbr,first_name,last_name, medication_name, cast(icd_code_id as varchar(500)) diag,
row_number() over(partition by person_nbr order by person_nbr, first_name, last_name,medication_name) rn
from ta_pivot
) src
unpivot
(
value
for col in (diag)
) unpiv
) d
pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute(#query);