I trying to write a query and I need some help.
I have some data that looks like this:
However, the end users would like a Pivot so that the data displays like this:
I wrote this code:
SELECT *
FROM
(
SELECT TOP 100
Log0.sn
,CONVERT(VARCHAR(50), Log0.capture_time) AS Instant
,CONVERT(VARCHAR(50),Log0.address) + '/' + Log0.[Key] AS 'Address/Key'
,Log0.average AS Command
,Log1.average AS Actual
FROM ih3_fan_speed_log_0 Log0
LEFT JOIN ih3_fan_speed_log_01 Log1 ON Log0.sn = Log1.sn AND
Log0.capture_time = Log1.capture_time AND Log0.address = Log1.address
WHERE Log0.sn = 'V300188' AND Log0.capture_time = '03/26/2017 13:05:00'
) Src
pivot
(
MAX(sn)
for Instant in ([1], [2], [3], [4])
) piv;
But that returns:
My questions are:
1) Why doesn't my Pivot work ?
2) Is it even possible to do what I need with a Pivot ?
Thanks for any help.
Per request, here is the data:
sn Instant Address/Key Command Actual
V300188 Mar 26 2017 1:05PM 1/EF-1 99.23 99.24
V300188 Mar 26 2017 1:05PM 2/EF-2 99.02 99.04
V300188 Mar 26 2017 1:05PM 3/EF-3 100 0
V300188 Mar 26 2017 1:05PM 4/EF-4 100 100
V300188 Mar 26 2017 1:05PM 41/MUA-1 74.58 74.58
V300188 Mar 26 2017 1:05PM 51/0-10VDC 74.58 74.58
Here is the result set:
Address/Key Command Actual 1 2 3 4
1/EF-1 99.23 99.24 NULL NULL NULL NULL
2/EF-2 99.02 99.04 NULL NULL NULL NULL
3/EF-3 100 0 NULL NULL NULL NULL
4/EF-4 100 100 NULL NULL NULL NULL
41/MUA-1 74.58 74.58 NULL NULL NULL NULL
51/0-10VDC 74.58 74.58 NULL NULL NULL NULL
Here is how you can leverage a dynamic crosstab to accomplish this type of thing. Jeff Moden has a fantastic article explaining this technique here. http://www.sqlservercentral.com/articles/Crosstab/65048/
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
sn varchar(10)
, Instant datetime
, [Address/Key] varchar(20)
, Command numeric(7,2)
, Actual numeric(7,2)
)
insert #Something
select 'V300188', 'Mar 26 2017 1:05PM', '1/EF-1', 99.23, 99.24 union all
select 'V300188', 'Mar 26 2017 1:05PM', '2/EF-2', 99.02, 99.04 union all
select 'V300188', 'Mar 26 2017 1:05PM', '3/EF-3', 100, 0 union all
select 'V300188', 'Mar 26 2017 1:05PM', '4/EF-4', 100, 100 union all
select 'V300188', 'Mar 26 2017 1:05PM', '41/MUA-1', 74.58, 74.58 union all
select 'V300188', 'Mar 26 2017 1:05PM', '51/0-10VDC', 74.58,74.58
declare #MaxCols int
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by sn order by instant) as RowNum
from #Something
)
select sn, instant';
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by sn, instant order by sn';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then [Address/Key] end) as address' + CAST(N as varchar(6)) + CHAR(10) +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Command end) as Command' + CAST(N as varchar(6)) + CHAR(10) +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Actual end) as Actual' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by sn, instant
order by COUNT(*) desc
)
select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute
Another Option for a Dynamic Pivot
The twist was the non-distinct/repeating columns in the final results. As you can see, this was resolved with a simple replace (x3).
Declare #SQL varchar(max) = Stuff((Select Distinct ','+QuoteName(concat('A',ColGrp))
+','+QuoteName(concat('B',ColGrp))
+','+QuoteName(concat('C',ColGrp))
From (Select Distinct ColGrp=Row_Number() over (Partition By sn,Instant Order by [Address/Key]) From YourTable ) A
Order By 1
For XML Path('')),1,1,'')
Select #SQL = '
Select [SN],[Instant],' + replace(replace(replace(#SQL,'[A','[Address/Key]=[A'),'[C','[Actual]=[C'),'[B','[Command]=[B') + '
From (
Select [SN]
,[Instant]
,[Col] = Concat(B.Prefix,RN )
,B.Value
From (Select *,RN=Row_Number() over (Partition By sn,Instant Order by [Address/Key]) From YourTable) A
Cross Apply (values (''A'',[Address/Key])
,(''B'',cast(Command as varchar(25)))
,(''C'',cast(Actual as varchar(25)))
) B (PreFix,Value)
) A
Pivot (max([Value]) For [Col] in (' + #SQL + ') ) p'
--Print #SQL
Exec(#SQL);
Returns
EDIT - If it Helps with the Visualization
The generated SQL Looks like this
Select [SN],[Instant],[Address/Key]=[A1],[Command]=[B1],[Actual]=[C1],[Address/Key]=[A2],[Command]=[B2],[Actual]=[C2],[Address/Key]=[A3],[Command]=[B3],[Actual]=[C3],[Address/Key]=[A4],[Command]=[B4],[Actual]=[C4],[Address/Key]=[A5],[Command]=[B5],[Actual]=[C5],[Address/Key]=[A6],[Command]=[B6],[Actual]=[C6]
From (
Select [SN]
,[Instant]
,[Col] = Concat(B.Prefix,RN )
,B.Value
From (Select *,RN=Row_Number() over (Partition By sn,Instant Order by [Address/Key]) From YourTable) A
Cross Apply (values ('A',[Address/Key])
,('B',cast(Command as varchar(25)))
,('C',cast(Actual as varchar(25)))
) B (PreFix,Value)
) A
Pivot (max([Value]) For [Col] in ([A1],[B1],[C1],[A2],[B2],[C2],[A3],[B3],[C3],[A4],[B4],[C4],[A5],[B5],[C5],[A6],[B6],[C6]) ) p
Related
Now, I have a pivoted query that will bring a set of events that took place on all the towns registered in a table and a date range.
This is my query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
CREATE TABLE #tempDates
(
[FechaSt] Datetime
);
;WITH cte1 (S) AS (
SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (S)
),
cte2 (S) AS (SELECT 1 FROM cte1 AS cte1 CROSS JOIN cte1 AS cte2),
cte3 (S) AS (SELECT 1 FROM cte1 AS cte1 CROSS JOIN cte2 AS cte2)
INSERT INTO #tempDates
SELECT
[Result] AS [Fecha]
FROM
(
SELECT
DISTINCT CAST([Result] AS DATE) [Result] FROM
(
SELECT
TOP (DATEDIFF(day, #f1, #f2) + 1)
[Result] = DATEADD(day, ROW_NUMBER() OVER(ORDER BY S) - 1, #f1)
FROM cte3
) AS res
) AS [listaFechas];
select #cols =
STUFF
(
(
SELECT
DISTINCT ',' + QUOTENAME(convert(CHAR(10), d.FechaSt, 120))
FROM #tempDates d
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,''
)
SET #query =
'
SELECT
IdMunicipio,
Ciudad,
Region,
Base,
' + #cols + '
FROM
(
SELECT
[Jc].[ID],
[Jc].[IdMunicipio],
[Wc].[Ciudad],
[Wr].[Region],
IIF
(
[Mk].[EsBase] = 1,
''<i class="fas fa-star fa-fw textoAmarilloSm"></i>'',
''''
) AS [Base],
CAST([Jc].[Fecha] AS date) AS [FechaJc]
FROM [dbo].[Jornadas_Cronograma] [Jc]
INNER JOIN
[dbo].[L_MunicipiosCapacitacion] [Mk]
ON [Jc].[IdMunicipio] = [Mk].[ID]
INNER JOIN
[dbo].[L_RegionesMundo] [Wr]
ON [Mk].[RegionId] = [Wr].[RegionID]
INNER JOIN
[dbo].[L_CiudadesMundo] [Wc]
ON [Mk].[CiudadId] = [Wc].[CityID]
) X
PIVOT
(
COUNT([ID])
FOR [FechaJc] IN (' + #cols + ')
) pvt
ORDER BY Ciudad ASC
'
execute(#query);
So, according to the specified date range (#f1 and #f2), I'm creating a temp table that stores all the dates within that range, to stuff that data afterwards to achive the pivot.
This is a sample of the data returned:
IdMunicipio | Ciudad | ... | 2022-10-02 | 2022-10-03 | 2022-10-04
1 | Bogotá | ... | 0 | 1 | 3
2 | Cali | ... | 0 | 12 | 3
3 | Medell.| ... | 0 | 0 | 0
4 | Buga | ... | 0 | 10 | 0
5 | Chía | ... | 0 | 0 | 0
6 | Cota | ... | 0 | 0 | 0
7 | Cajicá | ... | 0 | 0 | 2
What I need is to filter this query, so that it will only bring the towns that had at least 1 event within the date range, for this example it will be:
IdMunicipio | Ciudad | ... | 2022-10-02 | 2022-10-03 | 2022-10-04
1 | Bogotá | ... | 0 | 1 | 3
2 | Cali | ... | 0 | 12 | 3
4 | Buga | ... | 0 | 10 | 0
7 | Cajicá | ... | 0 | 0 | 2
What I have tryed:
DROP TABLE #tempDates
DECLARE #f1 datetime = '2022-10-02';
DECLARE #f2 datetime = '2022-10-08';
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
CREATE TABLE #tempDates
(
[FechaSt] Datetime
);
;WITH cte1 (S) AS (
SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (S)
),
cte2 (S) AS (SELECT 1 FROM cte1 AS cte1 CROSS JOIN cte1 AS cte2),
cte3 (S) AS (SELECT 1 FROM cte1 AS cte1 CROSS JOIN cte2 AS cte2)
INSERT INTO #tempDates
SELECT
[Result] AS [Fecha]
FROM
(
SELECT
DISTINCT CAST([Result] AS DATE) [Result] FROM
(
SELECT
TOP (DATEDIFF(day, #f1, #f2) + 1)
[Result] = DATEADD(day, ROW_NUMBER() OVER(ORDER BY S) - 1, #f1)
FROM cte3
) AS res
) AS [listaFechas];
select #cols =
STUFF
(
(
SELECT
DISTINCT ',' + QUOTENAME(convert(CHAR(10), d.FechaSt, 120))
FROM #tempDates d
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,''
)
SET #query =
'
SELECT
IdMunicipio,
Ciudad,
Region,
Base,
' + #cols + '
FROM
(
SELECT
[Jc].[ID],
[Jc].[IdMunicipio],
[Wc].[Ciudad],
[Wr].[Region],
IIF
(
[Mk].[EsBase] = 1,
''<i class="fas fa-star fa-fw textoAmarilloSm"></i>'',
''''
) AS [Base],
CAST([Jc].[Fecha] AS date) AS [FechaJc]
FROM [dbo].[Jornadas_Cronograma] [Jc]
INNER JOIN
[dbo].[L_MunicipiosCapacitacion] [Mk]
ON [Jc].[IdMunicipio] = [Mk].[ID]
INNER JOIN
[dbo].[L_RegionesMundo] [Wr]
ON [Mk].[RegionId] = [Wr].[RegionID]
INNER JOIN
[dbo].[L_CiudadesMundo] [Wc]
ON [Mk].[CiudadId] = [Wc].[CityID]
WHERE
(
(
SELECT
COUNT(*)
FROM [dbo].[Jornadas_Cronograma] [Jb]
WHERE
(CAST([Jb].[Fecha] as date) BETWEEN ' + CAST(#f1 as date) + ' AND ' + CAST(#f2 as date) + ')
)
) > 0;
) X
PIVOT
(
COUNT([ID])
FOR [FechaJc] IN (' + #cols + ')
) pvt
ORDER BY Ciudad ASC
'
execute(#query);
But this will break into an error:
Msg 402, Level 16, State 1, Line 92
The data types nvarchar(max) and date are incompatible in the add operator.
This is breaking in the line where I declare the WHERE Clause:
(CAST([Jb].[Fecha] as date) BETWEEN ' + CAST(#f1 as date) + ' AND ' + CAST(#f2 as date) + ')
I've thinked that maybe if a somehow SUM the results for the dates columns, I will be able to filter where that sum is > 0, but I'm not being able to solve the syntax.
Here is my tables structure
Result
id ResultId CategoryId Total Attempted Score
----------------------------------------------------
1 8 1 30 25 20
2 8 2 30 30 19
3 8 3 30 27 21
4 7 1 20 15 10
5 7 2 20 20 15
Category
Id CategoryName
-----------------------
1 General
2 Aptitude
3 Technical
I want data in the below format
For ResultId = 8
Id General Aptitude Technical Total
--------------------------------------------------
8 20 19 21 60
For ResultId = 7
Id General Aptitude Total
-------------------------------------
7 10 15 25
I need a help to fetch the data in above format.
NOTE: The final fetched data contains score from Result table but having a column names from category table and according to CategoryId in Result table. Column name will be dynamic
Tried the below code (just for testing) but didn't work
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
SELECT #PivotColumns= COALESCE(#PivotColumns + ',','') + QUOTENAME(CategoryName)
FROM ( SELECT DISTINCT CategoryName
FROM [dbo].[Category] c) AS PivotExample
SET #SQLQuery =
N'SELECT DISTINCT ' + #PivotColumns + '
FROM [dbo].[Category] c
PIVOT( SUM(c.Id)
FOR CategoryName IN (' + #PivotColumns + ')) AS P'
EXEC sp_executesql #SQLQuery
My query will give you the expected output. You can check the output in SQL Fiddle
--dynamic with case
DECLARE #Sql NVARCHAR(4000) = NULL
DECLARE #ColumnHeaders NVARCHAR(4000);
SET #ColumnHeaders = STUFF((
SELECT DISTINCT ',' + 'Max(CASE WHEN rn =' + quotename(rn, '''') + ' THEN Score else null end ) as ' + CategoryName + CHAR(10) + CHAR(13)
FROM (
SELECT CategoryName, row_number() OVER (ORDER BY CategoryName) rn
FROM ( SELECT DISTINCT CategoryName FROM Category) t0
) t1
FOR XML PATH('')
,TYPE
).value('.', 'varchar(max)'), 1, 1, '');
--print #ColumnHeaders
SET #sql = N' ;with cte as (
select * , Row_number() Over(Partition by ResultId Order by ResultId ) rn from
Result)
Select ResultId, ' + #ColumnHeaders + ', SUM(Score) Total from cte Group by
ResultId ';
EXECUTE sp_executesql #sql
I am using SQL Server
I have a table TT that looks like this
TargetID RowID Actual
0001 1 0
0001 2 1
0001 3 1
0002 1 0
0002 2 1
0002 3 0
0003 1 1
0003 2 1
0003 3 0
How can I pivot it is to this
RowID Target0001 Target0002 Target0003
1 0 0 1
2 1 1 1
3 1 0 0
I tried
SELECT 'TargetID' + TargetID, RowID, Actual
FROM TT
WHERE TargetID = '0001'
UNION ALL
SELECT 'TargetID' + TargetID, RowID, Actual
FROM TT
WHERE TargetID = '0002'
SELECT 'TargetID' + TargetID, RowID, Actual
FROM TT
WHERE TargetID = '0003'
But there are 3000 TargetIDs and my method is not good for that
Any idea how to do that?
You can try this...
DECLARE #ColumnsTable TABLE ([ColumnName] VARCHAR(50));
INSERT INTO #ColumnsTable ([ColumnName])
SELECT DISTINCT '[' + CONVERT(VARCHAR(48), [TargetID]) + ']'
FROM TT;
DECLARE #PivotColumns VARCHAR(MAX), #TotalColumn VARCHAR(MAX), #SQL VARCHAR(MAX);
SET #PivotColumns = (SELECT STUFF((SELECT DISTINCT ', ' + CONVERT(VARCHAR(50), [ColumnName])
FROM #ColumnsTable
FOR XML PATH('')), 1, 2, ''));
SET #SQL = 'SELECT RowID,' +#PivotColumns +'
FROM (
SELECT RowID,TargetID,Actual
FROM TT) AS t
PIVOT (MAX([Actual])
FOR [TargetID] IN (' + #PivotColumns + ')) AS p';
EXEC(#SQL);
Using MS SQL Server and I have below table:
+-----------+------------------+------------------+---------------------+-------------------------+
| SrNo | ApprCode | ApprName | ApprStatus | ApprDate |
+-----------+------------------+------------------+---------------------+-------------------------+
| SR_176 | X001 | James | APR | 2019-10-03 |
| SR_176 | X002 | Sam | APR | 2019-10-03 |
+-----------+------------------+------------------+---------------------+-------------------------+
Tried with PIVOT but its showing james and X001 as a column heading:
Expected Result:
+-----------+-------------- +---------------+---------------------+-------------------------+------------------+
SrNo | ApprCode_1 | ApprName_1 | ApprDate_2 ApprCode_2 ApprName_2 ApprDate_2
+-----------+---------------+---------------+---------------------+-------------------------+------------------+
SR_176 X001 James 2019-10-03 X002 Sam 2019-10-03
+-----------+---------------+---------------+---------------------+---- ---------------------+------------------+
Query to generate data:
CREATE TABLE #Temp
(
SrNo NVARCHAR(200),
ApprCode NVARCHAR(200),
ApprName NVARCHAR(200),
ApprDate Date
)
INSERT INTO #Temp VALUES ('SR_176','X001','James', '2019-10-03')
INSERT INTO #Temp VALUES ('SR_176','X002','Sam', '2019-10-03')
Query that I tried:
declare #sql nvarchar(max)
declare #name_concat nvarchar(max)
declare #name1_concat nvarchar(max)
declare #select_aggs nvarchar(max)
select #name_concat = STUFF((select distinct ',' + quotename(ApprCode) from #Temp order by 1 for xml path('')), 1, 1, '')
select #name1_concat = STUFF((select distinct ',' + quotename(ApprName) from #Temp order by 1 for xml path('')), 1, 1, '')
select #sql = '
;with cte2 as
(
SELECT SrNo,' + #name_concat + ',' + #name1_concat + '
FROM #Temp
PIVOT(MAX(ApprCode)
FOR ApprCode IN (' + #name_concat + ')) AS PVTTable PIVOT
(
MAX(ApprName)
FOR ApprName IN (' + #name1_concat + ')) AS PVTTable1
)
select * from cte2
'
exec sp_executesql #sql
In fact, This is not a SQL Pivot situation and the sample data for question is not enough to test it completely but you can find the main idea :
Select
SrNo,
MAX(IIF(ApprCode = 'X001', ApprCode, null)) as ApprCode_1,
MAX(IIF(ApprCode = 'X001', ApprName, null)) as ApprName_1,
MAX(IIF(ApprCode = 'X001', ApprDate, null)) as ApprDate_1,
MAX(IIF(ApprCode = 'X002', ApprCode, null)) as ApprCode_2,
MAX(IIF(ApprCode = 'X002', ApprName, null)) as ApprName_2,
MAX(IIF(ApprCode = 'X002', ApprDate, null)) as ApprDate_2
From #Temp
Group by SrNo
This code works if ApprCode was the key to make two separate columns & SrNo is for the group by between rows.
I solved it by using ROW_NUMBER() and Case Expression:
Here is the query:
SELECT *,
Row_number()
OVER(
partition BY srno
ORDER BY apprdate) AS RN
INTO #temptable
FROM #temp
SELECT srno,
CASE rn
WHEN 1 THEN Max(apprname)
END AS [1 Approver],
CASE rn
WHEN 2 THEN Max(apprname)
END AS [2 Approver],
CASE rn
WHEN 1 THEN Max(apprcode)
END AS [1 ApproverCode],
CASE rn
WHEN 2 THEN Max(apprcode)
END AS [2 ApproverCode],
CASE rn
WHEN 1 THEN Max(apprdate)
END AS [1 Date],
CASE rn
WHEN 2 THEN Max(apprdate)
END AS [2 Date]
INTO #james
FROM #temptable
GROUP BY srno,
rn
SELECT srno,
Max([1 approver]) AS ApproverName_1,
Max([1 approvercode]) AS ApproverCode_1,
Max([1 date]) AS ApproverDate_1,
Max([2 approver]) AS ApproverName_2,
Max([2 approvercode]) AS ApproverCode_2,
Max([2 date]) AS ApproverDate_2
FROM #james
GROUP BY srno
This question already has answers here:
Transpose rows and columns with no aggregate
(2 answers)
Closed 8 years ago.
I have tried viewing other posts on the subject but all the examples I've seen are based on knowing a specific value.
Example of what I have:
Address Name Number
------- ------- -------
1234 Main Bob 555-555-5555
1234 Main Karen 444-444-4444
1990 Maple Susie 333-333-3333
1010 12th Joe 222-222-2222
1010 12th Beth 111-111-1111
1010 12th Steve 444-433-3221
Example of what I want:
Address Contact1 Contact2 Contact3
------- ------- -------- --------
1234 Main Bob:555-555-5555 Karen:444-444-4444 NULL
1990 Maple Susie:333-333-3333 NULL NULL
1010 12th Joe: 222-222-2222 Beth 111-111-1111 Steve 444-433-3221
There are thousands of rows so I can't CASE and.. I'm a more than a little lost here.
Any suggestions?
I think you can use the following query. This assumes you have maximum three contacts
;WITH orderedAddress(Address,Name,Number,Sort)
AS
(
SELECT Address,Name,Number,ROW_NUMBER() OVER(PARTITION BY Address ORDER BY Name) AS num
FROM Addresses
)
SELECT main.Address,Contact1.Name + ':' + Contact1.Number AS Contact1 ,
Contact2.Name + ':' + ISNULL(Contact2.Number,'') AS Contact2 ,
Contact3.Name + ':' + ISNULL(Contact3.Number,'') AS Contact3
FROM
(SELECT DISTINCT Address FROM Addresses) AS main
LEFT JOIN OrderedAddress Contact1 ON main.Address = Contact1.Address AND Contact1.Sort=1
LEFT JOIN OrderedAddress Contact2 ON main.Address = Contact2.Address AND Contact2.Sort=2
LEFT JOIN OrderedAddress Contact3 ON main.Address = Contact3.Address AND Contact3.Sort=3
A dynamic pivot will work but so will a dynamic cross tab. Generally speaking a cross tab will beat the pivot for performance. Here is an example of one I posted just a few days ago.
if OBJECT_ID('Something') is not null
drop table Something
create table Something
(
ID int,
Subject1 varchar(50)
)
insert Something
select 10868952, 'NUR/3110/D507' union all
select 10868952, 'NUR/3110/D512' union all
select 10868952, 'NUR/4010/D523' union all
select 10868952, 'NUR/4010/HD20' union all
select 12345, 'asdfasdf'
declare #MaxCols int
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by ID order by Subject1) as RowNum
from Something
)
select ID';
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by ID order by ID';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Subject1 end) as Subject' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from Something
group by ID
order by COUNT(*) desc
)
select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute