How to get column wise data in SQL Server?
Format:
Name Date
---- -----
xxx 10/15/2015
xxx 12/15/2015
xxx 15/15/2015
yyy 20/15/2015
yyy 25/15/2015
Desired output:
Name Date Date Date
--------------------------------------------
xxx 10/15/2015 12/15/2015 15/15/2015
yyy 20/15/2015 25/15/2015
You can use this code for example which will pivot the data:
On MySQL:
SELECT data.name,
if(data.row_number=1,date,null) as date1,
if(data.row_number=2,date,null) as date2,
if(data.row_number=3,date,null) as date3,
if(data.row_number=4,date,null) as date4,
if(data.row_number=5,date,null) as date5
FROM (
SELECT #row_number:=#row_number+1 AS row_number, name, date
FROM yourTable, (SELECT #row_number:=0) AS t
ORDER BY date
) as data
GROUP BY data.name;
On SQL Server:
-- Generate demo data
CREATE TABLE #yourTable(name nvarchar(20), date date)
INSERT INTO #yourTable(name,date)
VALUES(N'xxx',GETDATE()), (N'xxx', DATEADD(day,-1,GETDATE())), (N'yyy',GETDATE()), (N'yyy', DATEADD(day,1,GETDATE()))
-- this is your part
SELECT pvt.*
FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY name ORDER BY date) as rn, name, date
FROM #yourTable
) as data
PIVOT(
MIN(date)
FOR rn IN([1],[2],[3],[4],[5],[6])
) as pvt
-- cleanup
DROP TABLE #yourTable
This will be a dynamic pivot which will adapt if your date list will grow:
-- Generate demo data
CREATE TABLE #yourTable(name nvarchar(20), date date)
INSERT INTO #yourTable(name,date)
VALUES(N'xxx',GETDATE()), (N'xxx',DATEADD(day,1,GETDATE())), (N'xxx', DATEADD(day,-1,GETDATE())), (N'yyy',GETDATE()), (N'yyy', DATEADD(day,1,GETDATE()))
DECLARE #sql nvarchar(max), #columnlist nvarchar(max)
SELECT #columnlist =
COALESCE(#columnlist + N',['+CONVERT(nvarchar(max),ROW_NUMBER() OVER(ORDER BY date))+']',
N'['+CONVERT(nvarchar(max),ROW_NUMBER() OVER(ORDER BY date))+']'
)
FROM #yourTable
WHERE name = (
SELECT TOP (1) name
FROM #yourTable
GROUP BY name
ORDER BY COUNT(*) DESC
)
SELECT #columnlist
-- this is your part
SET #sql = N'
SELECT pvt.*
FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY name ORDER BY date) as rn, name, date
FROM #yourTable
) as data
PIVOT(
MIN(date)
FOR rn IN('+#columnlist+')
) as pvt'
EXEC(#sql)
-- cleanup
DROP TABLE #yourTable
may be this will suits your requirement
declare #t table (name varchar(5),dated varchar(10))
insert into #t (name,dated)values
('xxx','10/15/2015'),('xxx','12/15/2015')
,('yyy','15/15/2015'),('yyy','20/15/2015'),('yyy','25/15/2015')
Select name,[1]As [Date],[2]As [Date],[3]As [Date] from (
select name,dated,ROW_NUMBER()OVER(PARTITION BY name ORDER BY dated)RN from #t
)T
PIVOT(MIN(dated) FOR RN IN ([1],[2],[3]))P
Related
I am trying to create dynamic pivot query in SQL but my issue is that the contract id and the tier desc columns are both dynamic and I could not figure out how to solve this issue. I have something like this:
and this is the output I would like to see
This can be done with repeating column names, however, I can't imagine why one would want this.
The #Col is where we apply the Alias ...[#] as [Tier Value]...
Example
Declare #Col varchar(max) = Stuff((Select Distinct ',' + concat(QuoteName(row_number() over (Partition By ContractID Order by TierDesc)),' as [Tier Value]') From Yourtable Order by 1 For XML Path('')),1,1,'')
Declare #SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(row_number() over (Partition By ContractID Order by TierDesc)) From Yourtable Order by 1 For XML Path('')),1,1,'')
Select #SQL = '
Select ContractID,'+#Col+'
From (
Select ContractID
,TierDesc
,ColNr = row_number() over (Partition By ContractID Order by TierDesc)
From YourTable
) Src
Pivot (max(TierDesc) for ColNr in ('+#SQL+') ) pvt
'
Exec(#SQL)
Returns
ContractID Tier Value Tier Value Tier Value
123 tier1 tier2 NULL
555 tier4 tier5 tier6
652 tier0 tier4 NULL
EDIT - Then generated SQL Looks like this
Select ContractID
,[1] as [Tier Value]
,[2] as [Tier Value]
,[3] as [Tier Value]
From (
Select ContractID
,TierDesc
,ColNr = row_number() over (Partition By ContractID Order by TierDesc)
From YourTable
) Src
Pivot (max(TierDesc) for ColNr in ([1],[2],[3]) ) pvt
EDIT 2
Select Distinct
ColNr = row_number() over (partition by ContractID Order By TierDesc)
From Yourtable
I want to convert rows as column (like PIVOT) and i am unable to get if the number of values increases.
Below is my table.
i want the output like this.
I have used the following queries to acheive this but no luck.
Query1
Create table #temp(instanceid int, submissionid int, name1 varchar(20), value1 varchar(20))
insert into #temp(instanceid,submissionid,name1,value1)
Select 5151,5532,'Question_1','Y'
union
Select 5151,5532,'First','Mujda'
union
Select 5151,5532,'Last','Zhublawar'
union
Select 5151,5532,'Question_1','Y'
union
Select 5151,5532,'First','Mujda1'
union
Select 5151,5532,'Last','Zhublawar1'
union
Select 5151,5532,'Question_1','Y'
union
Select 5152,5533,'First','Muthu'
union
Select 5151,5533,'Last','Kumar'
union
Select 5152,5533,'Question_1','Y'
union
Select 5152,5533,'First','Muthu1'
union
Select 5152,5533,'Last','Kumar1'
GO
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
DECLARE #PivotValues AS NVARCHAR(MAX)
--Get unique values of pivot column
SELECT #PivotColumns= COALESCE(#PivotColumns + ',','') + QUOTENAME(seq)
FROM (
select (cast(row_number() over(partition by name1 order by name1) as varchar(10)) + name1) as seq
from #temp group by value1,name1,instanceid
) AS PivotExample
--Create the dynamic query with all the values for
--pivot column at runtime
SET #SQLQuery =
N'SELECT instanceid,submissionid, ' + #PivotColumns + '
FROM #temp
PIVOT( MAX(value1)
FOR name1 IN (' + #PivotColumns + ')) AS P'
--Execute dynamic query
EXEC sp_executesql #SQLQuery
DROP TABLE #temp
Query2:
Create table #temp(instanceid int, submissionid int, name1 varchar(20), value1 varchar(20))
insert into #temp(instanceid,submissionid,name1,value1)
Select 5151,5532,'Question_1','Y'
union
Select 5151,5532,'First','Mujda'
union
Select 5151,5532,'Last','Zhublawar'
union
Select 5151,5532,'Interest','100'
select * from(
Select
instanceid,
submissionid,
[1st Ownership First Name] = Case when name1='First' then value1 end,
[1st Ownership Last Name] = Case when name1='Last' then value1 end,
[1st Ownership Question] = Case when name1='Question_1' then value1 end
from #temp
group by instanceid,submissionid,name1,value1
) P where p.[1st Ownership First Name] is not null or p.[1st Ownership Last Name] is not null or p.[1st Ownership Question] is not null
drop table #temp
You need an extra field to get some order in that data with all the duplicates.
For example a primary key.
Then you can use a pivot with a row_number that uses that extra field in the order by.
Then concat the row_number with the name1, and Pivot on those.
For example :
create table #temp (id int identity(1,1), instanceid int, submissionid int, name1 varchar(20), value1 varchar(20));
insert into #temp(instanceid,submissionid,name1,value1) values
(5151,5532,'First','Mujda'),
(5151,5532,'Last','Zhublawar'),
(5151,5532,'Question_1','Y'),
(5151,5532,'First','Mujda1'),
(5151,5532,'Last','Zhublawar1'),
(5151,5532,'Question_1','Y'),
(5151,5532,'First','Mujda1'),
(5151,5532,'Last','Zhublawar1'),
(5151,5532,'Question_1','Y'),
(5151,5533,'First','Muthu'),
(5151,5533,'Last','Kumar'),
(5151,5533,'Question_1','Y'),
(5151,5534,'First','Suresh'),
(5151,5534,'Last','Kumar'),
(5151,5534,'Question_1','Y'),
(5151,5534,'First','Suresh1'),
(5151,5534,'Last','Kumar1'),
(5151,5534,'Question_1','Y');
SELECT
instanceid,
submissionid,
[First1] as [1st First], [Last1] as [1st Last], [Question_11] as [1st Question_1],
[First2] as [2nd First], [Last2] as [2nd Last], [Question_12] as [2nd Question_1],
[First3] as [3rd First], [Last3] as [3rd Last], [Question_13] as [3rd Question_1]
FROM (
select
instanceid,
submissionid,
concat(name1, row_number() over (partition by instanceid, submissionid, name1 order by id)) as name_rn, value1
from #temp
where name1 in ('First','Last','Question_1')
) t
PIVOT( MAX(value1)
FOR name_rn IN (
[First1], [Last1], [Question_11],
[First2], [Last2], [Question_12],
[First3], [Last3], [Question_13]
)
) AS Pvt;
To do it the dynamic way, here's some SQL to generate a #SQL variable.
declare #T table (name1 varchar(20));
insert into #T select name1 from #temp group by name1 order by name1;
declare #SQL nvarchar(max);
declare #Fields1 nvarchar(max);
declare #Fields2 nvarchar(max);
SELECT #Fields2 = STUFF((select ', ' + quotename(name1) from #T order by name1 FOR XML PATH('')),1,1,'');
SET #Fields2 = replace(#Fields2,']','1]')+','+char(13)+replace(#Fields2,']','2]')+','+char(13)+replace(#Fields2,']','3]');
SELECT #Fields1 = STUFF((select ',$' + quotename(name1+n)+' as '+quotename(nx+' '+name1) from (
select '1' as n, '1st' as nx, name1 from #T union all
select '2', '2nd' as nx, name1 from #T union all
select '3', '3rd' as nx, name1 from #T
) q order by n, name1 FOR XML PATH('')),1,1,'');
SET #Fields1 = replace(#Fields1,'$',char(13));
SET #SQL =
'SELECT
instanceid,
submissionid,'+#Fields1+'
FROM (
select
instanceid,
submissionid,
concat(name1, row_number() over (partition by instanceid, submissionid, name1 order by id)) as name_rn, value1
from #temp
) t
PIVOT( MAX(value1)
FOR name_rn IN ('+char(13)+#Fields2+')
) AS Pvt';
select #SQL;
--Get unique values of pivot column
SELECT #PivotColumns= COALESCE(#PivotColumns + ',','') + QUOTENAME(seq)
FROM (
select DISTINCT (name1) as seq
from #temp group by value1,name1,instanceid
) AS PivotExample
This are is your problem you are concatenating a row_number into the name1 value which would always be null. Your column list needs to be the DISTINCT values in name1 NOT what you want them to be in the end. If you want to rename columns you would alias them after the pivot or change the value in name1 prior to running the pivot.
So in the above code I removed the ROW_NUMBER() and added DISTINCT to the derived table.
Also note the test data you included has some instanceid & submissionid combinations that are missing certain fields like first name, or question. It looks like when copying and pasting you just didn't correct the correlations.
I'm trying to convert my result table which consist of multiple rows into multiple columns. below are my sample result before and after:
Before:
After:
Got a some idea from here but still no luck.
Update 1:
select #cols = STUFF((select ',' + QUOTENAME(institution) + ',' + QUOTENAME(intstatus)
From #temp
group by refno,frmstatus
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
i have no idea how to insert each column into the pivot query
set #query = 'select refno, frmstatus,' + #cols + '
from (
select refno, frmstatus, institution, intstatus from #temp
) x
pivot
(
???????
)
Please try the below query:
CREATE TABLE #temp(refno nvarchar(20), firmstatus nvarchar(20), institution nvarchar(20), intstatus nvarchar(20), ranking int)
DECLARE #qu NVARCHAR(MAX), #pcol NVARCHAR(MAX)
INSERT INTO #temp
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY refno ORDER BY institution ASC) AS ranking
FROM temp
SELECT #pcol=
STUFF((
SELECT
DISTINCT N', Institution'+ CAST (ranking AS NVARCHAR(25)) +', '+ N'Intstatus'+ CAST (ranking AS NVARCHAR(25))
FROM #temp
FOR XML PATH('')),1,1,'')
SET #qu=N'SELECT refno, firmstatus,'+ #pcol +
N' FROM
(
select refno,firmstatus,ColData,colheader+ CAST(ranking as varchar) as colnames from
(select * from #temp)s
UNPIVOT
(ColData for colheader in ([institution], [intstatus])) up
)S
PIVOT
(MAX(ColData) FOR colnames IN ('+#pcol +N')) AS piv'
EXEC sp_executesql #qu -- execute the dynamic sql
DROP TABLE #temp -- remove the temp table
The temp table in above script was created like below
--create table temp( refno nvarchar(20), firmstatus nvarchar(20), institution nvarchar(20), intstatus nvarchar(20))
--insert into temp values
--('AAA/1','Active','InstA','Ongoing'),
--('AAA/1','Active','InstB','Ongoing'),
--('AAA/1','Active','InstC','Ongoing'),
--('AAA/2','Active','InstA','Ongoing'),
--('AAA/2','Active','InstB','Ongoing')
Result received:
If repeated columns number is small and restricted, you can use simple solution:
WITH A AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY refno, fmstatus ORDER BY institution) n
FROM myTable
),
B AS (
SELECT refno, fmstatus,
CASE WHEN n=1 THEN institution END institution,
CASE WHEN n=1 THEN intstatus END intstatus,
CASE WHEN n=2 THEN institution END institution1,
CASE WHEN n=2 THEN intstatus END intstatus1,
CASE WHEN n=3 THEN institution END institution2,
CASE WHEN n=3 THEN intstatus END intstatus2
FROM A
)
SELECT refno, fmstatus,
MAX(institution) institution,
MAX(intstatus) intstatus,
MAX(institution1) institution1,
MAX(intstatus1) intstatus1,
MAX(institution2) institution2,
MAX(intstatus2) intstatus2
FROM B
GROUP BY refno, fmstatus
Otherwise use PIVOT
In the below image I have current data and expected data based on the first three columns the data need to get transpose
Table query:
drop table ##Test
CREATE TABLE ##Test
(paymentid varchar(30),
claimid bigint,
Lineno1 int,
groupcode varchar(2),
Carc int,
adjustmentamt float,
RARC varchar(30),
Edit1 varchar(30),
Remit varchar(30),
)
INSERT INTO ##Test
(paymentid ,
claimid ,
Lineno1 ,
groupcode ,
Carc ,
adjustmentamt ,
RARC ,
Edit1 ,
Remit )
VALUES
('QP18502291',14205893514,2,'CO',84,75.55,'N20','','D18')
('QP15930339',14127612308,1,'OA',23,263,'','ClaimDetail.COBAmt','') ,
('QP15930339',14127612308,1,'OA',23,21.69,'','ClaimDetail.COBAmt',''),
('QP18502291',14205893514,2,'OA',23,78.77,'','ClaimDetail.COBAmt',''),
('QP18502291',14205893514,2,'OA',97,66.55,'N20','','D18')
select * from ##Test
Possible duplicate post and take a look at the solution.
See SQL Fiddle with Demo.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(col+cast(rn as varchar(10)))
from
(
select row_number() over(partition by paymentid order by Lineno1) rn
from ##Test
) d
cross apply
(
select 'groupcode', 1 union all
select 'carc', 2 union all
select 'adjustmentamt', 3 UNION ALL
SELECT 'rarc',4 UNION ALL
SELECT 'Edit1' ,5 UNION ALL
SELECT 'remit',6
) c (col, so)
group by col, rn, so
order by rn, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT paymentid, claimid,Lineno1,' + #cols + '
from
(
select paymentid, claimid,Lineno1, col+cast(rn as varchar(10)) col, value
from
(
select paymentid, claimid,Lineno1, groupcode, carc, adjustmentamt,rarc,Edit1,remit,
row_number() over(partition by paymentid order by Lineno1) rn
from ##Test
) t
cross apply
(
select ''groupcode'', groupcode union all
select ''carc'', cast(carc as varchar(50)) union all
select ''adjustmentamt'', cast(adjustmentamt as varchar(50)) union all
select ''rarc'', rarc union all
select ''Edit1'' , Edit1 union all
select ''remit'' , remit
) c (col, value)
) x pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute(#query)
I want to pivot and turn an existing table and generate a report(cross tabulated). You see vals column is determined by unique combination of date_a and date_e columns. I don't know how to do this.
Something like this:
Test data
CREATE TABLE #tbl(date_a DATE,date_e DATE, vals FLOAT)
INSERT INTO #tbl
VALUES
('2/29/2012','1/1/2013',28.47),
('2/29/2012','2/1/2013',27.42),
('2/29/2012','3/1/2013',24.36),
('3/1/2012','1/1/2013',28.5),
('3/1/2012','2/1/2013',27.35),
('3/1/2012','3/1/2013',24.39),
('3/6/2012','1/1/2013',27.75),
('3/6/2012','2/1/2013',26.63),
('3/6/2012','3/1/2013',23.66)
Query
SELECT
*
FROM
(
SELECT
tbl.date_a,
tbl.date_e,
vals
FROM
#tbl AS tbl
) AS SourceTable
PIVOT
(
SUM(vals)
FOR date_e IN ([1/1/2013],[2/1/2013],[3/1/2013])
) AS pvt
DROP TABLE #tbl
EDIT
If you do not know how many columns there is then you need to do a dynamic pivot. Like this:
The unique columns
DECLARE #cols VARCHAR(MAX)
;WITH CTE
AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY date_e ORDER BY date_e) AS RowNbr,
tbl.*
FROM
#tbl AS tbl
)
SELECT #cols=STUFF
(
(
SELECT
',' +QUOTENAME(date_e)
FROM
CTE
WHERE
CTE.RowNbr=1
FOR XML PATH('')
)
,1,1,'')
Dynamic pivot
DECLARE #query NVARCHAR(4000)=
N'SELECT
*
FROM
(
SELECT
tbl.date_a,
tbl.date_e,
vals
FROM
#tbl AS tbl
) AS SourceTable
PIVOT
(
SUM(vals)
FOR date_e IN ('+#cols+')
) AS pvt'
EXECUTE(#query)