根据排序逻辑,每个ID合并多行

时间:2019-08-23 03:55:46

标签: sql sql-server tsql

我有一张表格,其中包含我们学校每个学生的学术专业和未成年人的单独行。这意味着每个学生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还是很陌生,无法弄清楚要使用哪个函数。任何帮助将不胜感激!

3 个答案:

答案 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;