Distinct Row values as Columns Sql Server - sql-server-2005

I have a temp table with 3 Columns Like below,
JobID JobType JobValue
12 HR Jesica
23 MANAGER Ravi
5 MANAGER Jacob
60 EMPLOYEE Kiruan
45 MANAGER Abidam
27 HR Kamsura
21 MANAGER Chio Bin
87 EMPLOYEE Gamanya
22 HR Pradeep
56 HR Hari
67 EMPLOYEE Om
14 MANAGER Kiran
My result table should be like
JobID HR MANAGER EMPLOYEE
12
23
5
60
45
27
21
87
22
56
67
14
Jobvalue column values should come into result set.
I have tried like below.
Created a temp table with distict Jobtype row values.
then using while loop inseted JobValue column values into that table.
But it looks very dirty procedure.
Can any one give me a good suggesion to complete this.
Thanks,

You should be able to use the PIVOT function to get the result:
select jobid, hr, manager, employee
from yourtable
pivot
(
max(jobvalue)
for jobtype in (hr, manager, employee)
) piv;
See SQL Fiddle with Demo.
If you want to list the jobvalue under each jobType without showing the jobid, then you could use:
select hr, manager, employee
from
(
select jobtype, jobvalue,
row_number() over(partition by jobtype order by jobid) rn
from yourtable
) d
pivot
(
max(jobvalue)
for jobtype in (hr, manager, employee)
) piv;
See SQL Fiddle with Demo

Try this
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(jobtype)
from yourtable
group by jobtype
ORDER BY jobtype
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
--SELECT #cols
set #query = 'SELECT JobID,' + #cols + ' from
(
select JobID, jobtype, jobvalue from yourtable
) x
pivot
(
MAX(jobvalue)
for jobtype in (' + #cols + ')
) p '
execute(#query)

Related

How to use pivot function in sql server?

I have a table like this:
Factory indexcode grade
200 1 95
200 2 100
5000 1 85
5000 3 90
How can I get this result?
Factory. 1 2 3
200 95 100 -
5000 85 - 90
The indexcode varies between 1 to 6.
You can try below -
select factorycode,pv.*
from tablename
pivot
(max(grade) for indexcode in ([1],[2],[3])) as pv
If your indexcodes are fixed (1-6) in that case you can use following PIVOT query.
SELECT *
FROM TABLE_NAME
PIVOT ( Max(grade)
FOR indexcode IN ( [1], [2], [3],[4],[5],[6]) ) pvt
If your index code values are not fixed and can take any value, in that case you can go for dynamic pivot like following.
DECLARE #cols AS NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename(indexcode)
FROM TABLE_NAME
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE #query AS NVARCHAR(max) = ' SELECT *
FROM TABLE_NAME
PIVOT ( max(grade)
FOR indexcode IN ('+#cols+') ) pvt';
EXECUTE(#query)
DEMO

Group Columns based on Row ID

I have a table pulling data, like:
ID FID Value
001 20 200
001 20 400
001 50 600
002 50 100
How do write a query to get a column for each row ID that would sum the Value's?
For example, I want to return the following:
ID 20 50
001 600 600
002 NULL 100
A pattern like this:
SELECT
ID,
SUM(CASE WHEN FID = 20 THEN Value END) as sum20,
SUM(CASE WHEN FID = 50 THEN Value END) as sum50 --extend by adding more CASE WHEN rows
FROM
table
GROUP BY ID
..has the advantage of working in databases that don't support PIVOT syntax.
If you'd like PIVOT syntax:
SELECT ID, [20], [50] --extend by providing more values in square brackets
FROM
table
PIVOT
(
SUM(Value)
FOR FID IN ([20], [50]) --extend by providing more values in square brackets
) pvt
If you have dynamic list of FID's you can use dynamic query as below:
Declare #cols1 varchar(max)
Declare #query nvarchar(max)
Select #cols1 = stuff((select Distinct ','+QuoteName(Fid) from #data for xml path('')),1,1,'')
Set #query = ' Select * from (
Select Id, [Fid], [Value] from #data ) a
pivot (sum([Value]) for [Fid] in (' + #cols1 + ') ) p '
Exec sp_executesql #query

Sql query for Transpose of a dynamic Table

The sql table is as follows,
Name Salary NoticePeriod CTC
Jack 1520 15 123
Bruce 1423 35 165
and it contains about 1000 rows.
I need to do a transpose of this table ,such that the expected output is
Fields Jack Bruce Mike ..... Sam
Salary 1520 1423 235 .. 561
NoticePeriod 15 35 23 253
CTC 123 165 45 ... 125
I tried using Pivot and Unpivot function in Sql Server 2008 . But Since the Name record is large , Pivot query doesnt helps.
My sql attempt is follows,
SELECT *
FROM (
SELECT NAME,
Salary,
NoticePeriod,
CTC
FROM CTCTABLE WITH (NOLOCK)
) AS queryTable
UNPIVOT(Value FOR NAME IN (NAME, Salary, NoticePeriod, CTC)) AS unpv
PIvot(max(Value) FOR NAME IN (Salary, NoticePeriod, CTC)) pv
In your case, you should unpivot the columns Salary, NoticePeriod, CTC into rows, then PIVOT:
WITH Unpivoted
AS
(
SELECT Name, Fields, SalaryValue
FROM salaries AS s
UNPIVOT
(
SalaryValue
FOR Fields IN(Salary, NoticePeriod, CTC)
) AS u
)
SELECT Fields, jack,bruce
FROM Unpivoted AS u
PIVOT
(
MAX(SalaryValue)
FOR Name IN(Jack, Bruce)
) AS p;
The UNPIVOT will transform the columns Salary, NoticePeriod, CTC into values:
Then the pivot will pivot the salary values for each field value and transform the names into columns.
And of course you have to do it dynamically instead of writing list of names like this:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #colnames AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' +
QUOTENAME(name)
FROM salaries
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = 'WITH Unpivoted
AS
(
SELECT Name, Fields, SalaryValue
FROM salaries AS s
UNPIVOT
(
SalaryValue
FOR Fields IN(Salary, NoticePeriod, CTC)
) AS u
)
SELECT Fields, ' + #cols + '
FROM Unpivoted AS u
PIVOT
(
MAX(SalaryValue)
FOR Name IN(' + #cols + ')' +
') p';
execute(#query);
This will give you:
Live Demo (Thanks to #lad2025 for it)

SQL Server query for grouping row as column and getting corresponding designation

I have 2 tables in SQL Server:
Table 1 : Department
DeptId Dept Name
------------------
1 Software Development
2 Testing
3 Customization
Table 2 : Designation
DesigId Desig Name DeptId
---------------------------
1 TL 1
2 PL 1
3 TestEngg 2
4 SE 3
I want the following output which takes department as column heading and group designation under the corresponding department column,
Software Development Testing Customization
TL TestEngg SE
PL
I tried with the below query but Im able to get only the Id's
DECLARE #deptcols AS VARCHAR(MAX);
DECLARE #querystr AS VARCHAR(MAX);
select #deptcols = STUFF((SELECT distinct ',' + QUOTENAME(Dept_Id)
FROM Designation
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #querystr = 'SELECT ' + #deptcols + ' from
(
select Desig_Name, Dept_Id,Desig_Id
from Designation
) p
pivot
(
count(Desig_Id) FOR Dept_Id in (' + #deptcols + ')
) pv '
execute(#querystr)
Your code was so very close. My suggestion when working with PIVOT especially a dynamic version is to write the static version first, then convert it to dynamic sql.
The static version, where you hard-code values is like this:
SELECT [Software Development], [Testing], [Customization]
from
(
select d.[Dept Name],
s.[Desig Name],
row_number() over(partition by s.deptid order by s.desigid) rn
from Designation s
left join department d
on s.[DeptId] = d.[DeptId]
) p
pivot
(
max([Desig Name])
FOR [Dept Name] in ([Software Development], [Testing], [Customization])
) pv
See SQL Fiddle with Demo. The static version allows you to be sure that the syntax is correct and all values, columns etc are in the right places.
Then once you have the syntax it is easy to convert to the dynamic SQL version:
DECLARE #deptcols AS VARCHAR(MAX)
DECLARE #querystr AS VARCHAR(MAX)
select #deptcols = STUFF((SELECT ',' + QUOTENAME([Dept Name])
FROM Department
GROUP BY [Dept Name], DeptId
ORDER BY DeptId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #querystr =
'SELECT ' + #deptcols + ' from
(
select d.[Dept Name],
s.[Desig Name],
row_number() over(partition by s.deptid order by s.desigid) rn
from Designation s
left join department d
on s.[DeptId] = d.[DeptId]
) p
pivot
(
max([Desig Name])
FOR [Dept Name] in (' + #deptcols + ')
) pv '
execute(#querystr)
See SQL Fiddle with Demo
Both give the result:
| SOFTWARE DEVELOPMENT | TESTING | CUSTOMIZATION |
---------------------------------------------------
| TL | TestEngg | SE |
| PL | (null) | (null) |
You will notice that I added the line row_number() over(partition by s.deptid order by s.desigid) rn to the SELECT statement. This allows you to return more than one Desig Name for each Dept Name, without this you will only return one value.
I think PIVOT keyword is what you should use here. PIVOT can be used to transform datasets such that columns become rows.
No need to construct dynamic queries
Take a look at this article: http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=PIVOTData
More info: http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

Convert Rows to columns using 'Pivot' in mssql when columns are string data type

I need to know whether 'pivot' in MS SQL can be used for converting rows to columns if there is no aggregate function to be used. i saw lot of examples with aggregate function only. my fields are string data type and i need to convert this row data to column data.This is why i wrote this question.i just did it with 'case'. Can anyone help me......Thanks in advance.
You can use a PIVOT to perform this operation. When doing the PIVOT you can do it one of two ways, with a Static Pivot that you will code the rows to transform or a Dynamic Pivot which will create the list of columns at run-time:
Static Pivot (see SQL Fiddle with a Demo):
SELECT *
FROM
(
select empid, wagecode, amount
from t1
) x
pivot
(
sum(amount)
for wagecode in ([basic], [TA], [DA])
) p
Dynamic Pivot:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(wagecode)
FROM t1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT empid, ' + #cols + ' from
(
select empid, wagecode, amount
from t1
) x
pivot
(
sum(amount)
for wagecode in (' + #cols + ')
) p '
execute(#query)
Both of these will give you the same results
sample format
empid wagecode amount
1 basic 1000
1 TA 500
1 DA 500
2 Basic 1500
2 TA 750
2 DA 750
empid basic TA DA
1 1000 500 500
2 1500 750 750
THE ANSWER I GOT IS
SELECT empID , [1bas] as basic, [1tasal] as TA,[1otsal] as DA
FROM (
SELECT empID, wage, amount
FROM table) up
PIVOT (SUM(amt) FOR wgcod IN ([1bas], [1tasal],[1otsal])) AS pvt
ORDER BY empID
GO
Try this:
SELECT empid AS EmpID
, ISNULL(SUM(CASE wagecode WHEN 'basic' THEN Amount ELSE 0 END), 0) AS Basic
, ISNULL(SUM(CASE wagecode WHEN 'ta' THEN Amount ELSE 0 END), 0) AS TA
, ISNULL(SUM(CASE wagecode WHEN 'da' THEN Amount ELSE 0 END), 0) AS DA
FROM Employee
GROUP BY empid