我有一张表格,其中包含我们学校每个学生的学术专业和未成年人的单独行。这意味着每个学生ID通常有几行,因为学生可以是双主修,等等。我需要输出一个报告,该报告为每个学生提供单行,并根据将每个值都包含其他值的逻辑合并该数据行。
例如,我有一个这样的表:
ID Program_Code Type Sequence
-----------------------------------
123 11.1234 Major 1
123 55.5555 Minor 2
123 98.3454 Major 3
456 11.1234 Major 1
789 77.7777 Major 1
789 45.4545 Minor 2
000 77.7777 Major 2
000 88.8888 Major 3
000 22.2222 Minor 4
000 55.5555 Minor 5
我需要根据该信息为每个学生分配三个字段-小学专业,中学专业和未成年人。逻辑需要为每个程序使用序列号和类型来分配这些字段:
对于每个Type = Major的ID,Primary Major始终是最低的序列号
每个ID的Secondary Major将是具有第二低序号(其Type = Major)的程序。如果没有,则该ID的Secondary Major = 00.0000
每个ID的Minor将是具有最低序号且Type = Minor的Program。具有较高序号的其他未成年人将被忽略。如果没有次要行,则该ID的Minor = 00.0000
如您所见,序列号并不总是从1开始。
理想情况下,示例表的输出每个ID仅包含一行,并且看起来像这样:
ID Primary Secondary Minor
-------------------------------------
123 11.1234 98.3454 55.5555
456 11.1234 00.0000 00.0000
789 77.7777 00.0000 45.4545
000 77.7777 88.8888 22.2222
有没有简单的方法可以做到这一点?我正在尝试使用CONCAT和XML PATH,但对于SQL还是很陌生,无法弄清楚要使用哪个函数。任何帮助将不胜感激!
答案 0 :(得分:0)
我希望这对您有用:
select ID,
max(case when rankno = 1 and Type = "Major" then Program_code else "00.0000" end) as [Primary],
max(case when rankno = 2 and Type = "Major" then Program_code else "00.0000" end) as [Secondary],
max(case when rankno in (1,2,3) and Type = "Minor" then Program_code else "00.0000" end) as [Minor]
from
(
select ID, Program_code, Type,
rank () over (partition by ID order by ID, Type, Sequence) as rankno
from Programs
) as t
group by ID
order by ID
答案 1 :(得分:0)
您可以尝试一下。使用Row_number()
可以生成行序列顺序。之后,top 3
可以达到预期的效果,可以将其转到您尊敬的列。
; WITH CTE AS (
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY TYPE, SEQUENCE) AS SLNO, * FROM YOURTABLE
)
---- here column names can be increased by using dynamic query
SELECT ID, ISNULL([1],0) AS [PRIMARY], ISNULL([2],0) AS [SECONDARY], ISNULL([3],0) AS [MINOR] FROM
(
SELECT ID, SLNO, PROGRAM_CODE FROM CTE WHERE SLNO <= 3
) AS TB
PIVOT (
MAX(PROGRAM_CODE) FOR SLNO IN ( [1], [2], [3] )
) AS PV
答案 2 :(得分:0)
使用row_number()
,但要考虑类型:
select id,
max(case when type = 'Major' and seqnum = 1 then program_code end) as major,
max(case when type = 'Major' and seqnum = 2 then program_code end) as secondary,
max(case when type = 'Minor' and seqnum = 1 then program_code end) as minor
from (select t.*,
row_number() over (partition by id, type order by sequence) as seqnum
from t
) t
group by id;