[英]Split single column into multiple columns based on Rank Number
I want to spit a column into multiple columns based on the rank by partition or column type我想根据分区或列类型的排名将一列分成多列
Sample Input Data:样本输入数据:
STUDENT PROGRAM_ID DEG_TYPE PROGRAM_RN
1 Program1.MA MA 1
1 Program2.MA MA 1
2 Program1.PHD DOC 1
2 Program2.MA MA 2
3 Program.CERT CERT 3
3 Program1.PSYD DOC 1
3 Program2.MA MA 2
Expected Output预计 Output
Student Highest Program Second Highest Program Third Highest Program
1 Program1.MA, Program2.MA
2 Program1.PSYD Program2.MA
3 Program1.PHD Program2.MA Program.CERT
I have tried using PIVOT and I am able to split the column but with that I am able to fetch only one program as Highest, second and so on.我已经尝试使用 PIVOT 并且我能够拆分列,但是我只能获取一个程序作为最高、第二等等。 My requirement is to get all the Programs that has RN 1 listed for each student in highest program, all with RN 2 listed in Second and so on.我的要求是在最高课程中为每个学生列出 RN 1 的所有课程,所有课程都在第二课程中列出 RN 2,依此类推。
**CODE**
SELECT [STUDENTS_ID],[1], [2], [3]
FROM
(SELECT [STUDENTS_ID]
,[PROGRAM_ID]
,[PROGRAM_RN]
FROM [dbo].[CTE] ) AS SourceTable
PIVOT
(
MAX([PROGRAM_ID])
FOR [PROGRAM_RN] IN ([1], [2], [3])
) As PivotTable;
Current Output当前Output
Student Highest Program Second Highest Program Third Highest Program
1 Program1.MA
2 Program1.PSYD Program2.MA
3 Program1.PHD Program2.MA Program.CERT
I also want to know if there is a better way of doing this我也想知道是否有更好的方法来做到这一点
If you are using SQL 2017 or higher version, you can use string_agg function instead of XML PATH in below query else you can use the same query to dynamically achieve the result set you want.如果您使用的是 SQL 2017 或更高版本,则可以使用 string_agg function 而不是 XML PATH 在下面的查询中您想要动态实现相同的查询结果集。
DECLARE @Columns AS NVARCHAR(MAX),
@Query AS NVARCHAR(MAX)
SET @Columns = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.PROGRAM_RN)
FROM StudentTable c
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @Query = 'SELECT STUDENT, ' + @Columns + ' FROM
(
SELECT DISTINCT ST2.STUDENT ,PROGRAM_RN,
SUBSTRING(
(
SELECT '', ''+ST1.PROGRAM_ID AS [text()]
FROM dbo.StudentTable ST1
WHERE ST1.STUDENT = ST2.STUDENT AND ST1.PROGRAM_RN = ST2.PROGRAM_RN
ORDER BY ST1.STUDENT
FOR XML PATH ('''')
), 2, 1000) [PROGRAM_ID]
FROM dbo.StudentTable ST2
) x
PIVOT
(
MAX(PROGRAM_ID)
FOR PROGRAM_RN IN (' + @Columns + ')
) p '
EXEC(@Query)
Sort of odd that you have ties.有点奇怪,你有关系。 But you can use conditional aggregation with strings:但是您可以对字符串使用条件聚合:
select student,
string_agg(case when program_rn = 1 then program_id end, ', '),
string_agg(case when program_rn = 2 then program_id end, ', '),
string_agg(case when program_rn = 3 then program_id end, ', ')
from t
group by student;
If you know the maximum that need to be concatenated, you can use conditional aggregation:如果您知道需要连接的最大值,则可以使用条件聚合:
select student,
concat(max(case when program_rn = 1 and seqnum = 1 then program_id + '; ' end),
max(case when program_rn = 1 and seqnum = 2 then program_id + '; ' end),
max(case when program_rn = 1 and seqnum = 3 then program_id + '; ' end)
),
concat(max(case when program_rn = 2 and seqnum = 1 then program_id + '; ' end),
max(case when program_rn = 2 and seqnum = 2 then program_id + '; ' end),
max(case when program_rn = 2 and seqnum = 3 then program_id + '; ' end)
),
concat(max(case when program_rn = 3 and seqnum = 1 then program_id + '; ' end),
max(case when program_rn = 3 and seqnum = 2 then program_id + '; ' end),
max(case when program_rn = 3 and seqnum = 3 then program_id + '; ' end)
),
from (select t.*,
row_number() over (partition by student, program_rn order by program_id) as seqnum
from t
) t
group by student;
This is cumbersome, but possibly simpler than FOR XML PATH
.这很麻烦,但可能比FOR XML PATH
更简单。
Note that I changed the delimiter to a semicolon, because that seems more natural for leaving it at the end of the list.请注意,我将分隔符更改为分号,因为将其留在列表末尾似乎更自然。 Although it can be removed, that just further complicates the logic, perhaps unnecessarily.尽管可以将其删除,但这只会使逻辑更加复杂,也许是不必要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.