FirstName |LastName |OtherName |admim_no| ExamCategory | subject | Exam| Score| Grade
Anthony | Tee | Tony | 1000 | MockExams2014|Chemistry| PP1 | 12 | D+
Anthony | Tee | Tony | 1000 | MockExams2014|Biology | PP1 | 50 | C+
Moses K. | Ndu | | 1001 | MockExams2014|Chemistry| PP1 | 65 | B+
Moses K. | Ndu | | 1001 | MockExams2014|Biology | PP1 | 85 | A
我希望在sql server 2012中实现的是每个考试类别我已将admission_no分组为一行,然后将主题,考试,分数,成绩作为第二行的单独列放置,以便您拥有例如admission_no 1000和列的所有不同数据(主题,考试,分数,成绩)为单行。我不知道如何解决它。我尝试了下面的失败。
我的结果应该如下
Anthony | Tee | Tony | 1000| MockExams2014|Chemistry| PP1 | 12| D+ Biology| PP1 | 50| C+
SQLITE: merging rows into single row if they share a column
答案 0 :(得分:0)
如果允许将重复的值连接到on行,则可以使用XML PATH处理连接的子查询,在下面显示为add(2)。
要将重复值作为列获取,您可以计算admim_no的最大行数,并根据需要使用尽可能多的左连接来创建动态sql以获取所需的列。
/* test data
Create table TestX (FirstName varchar(50) ,LastName varchar(50),OtherName varchar(50), admim_no int,ExamCategory varchar(50), subject varchar(50), Exam Varchar(50), Score int,grade varchar(50))
Insert into TestX Values ('Anthony','Tee','Tony',1000 ,' MockExams2014','Chemistry','PP1',12,'D+')
Insert into TestX Values ('Anthony','Tee','Tony',1000 ,' MockExams2014','Biology','PP1',50,'C+')
Insert into TestX Values ('Moses K','Ndu',NULL,1001 ,' MockExams2014','Chemistry','PP1',65,'B+')
Insert into TestX Values ('Moses K','Ndu',NULL,1001 ,' MockExams2014','Biology','PP1',85,'A')
Insert into TestX Values ('Moses K','Ndu',NULL,1001 ,' MockExams2014','Physiks','PP2',12,'D+')
*/
Declare @maxcnt int
Declare @cnt int
Declare @Dyn1 varchar(max)
Declare @Dyn2 varchar(max)
Select @maxcnt=MAX(cnt) from
(Select COUNT(*) as cnt from TestX Group by admim_no ) a
Set @Dyn1='
;With CTE as
(
Select *, Row_Number() over (Partition by admim_no order by admim_no ) as rn from TestX
)
Select CTE0.*
'
Set @Dyn2='
From CTE CTE0'
Set @cnt=1
While @maxcnt>1
begin
Set @Dyn1 = @Dyn1 + ',CTE' + Cast(@cnt as varchar(5))+'.subject
,CTE' + Cast(@cnt as varchar(5))+'.Exam
,CTE' + Cast(@cnt as varchar(5))+'.Score
,CTE' + Cast(@cnt as varchar(5))+'.grade'
Set @Dyn2 = @Dyn2 + '
LEFT Join CTE CTE' + Cast(@cnt as varchar(5))+'
on CTE' + Cast(@cnt as varchar(5))+'.rn=CTE0.rn + '+Cast(@cnt as varchar(5))+'
and CTE' + Cast(@cnt as varchar(5))+'.admim_no=CTE0.admim_no'
Set @maxcnt=@maxcnt-1
Set @cnt=@cnt+1
end
Set @Dyn2 = @Dyn1 + @Dyn2 + '
where CTE0.rn=1'
Print @Dyn2
Exec(@Dyn2)
提供的测试数据的生成SQL如下所示:
;With CTE as
(
Select *, Row_Number() over (Partition by admim_no order by admim_no ) as rn from TestX
)
Select CTE0.*
,CTE1.subject
,CTE1.Exam
,CTE1.Score
,CTE1.grade,CTE2.subject
,CTE2.Exam
,CTE2.Score
,CTE2.grade
From CTE CTE0
LEFT Join CTE CTE1
on CTE1.rn=CTE0.rn + 1
and CTE1.admim_no=CTE0.admim_no
LEFT Join CTE CTE2
on CTE2.rn=CTE0.rn + 2
and CTE2.admim_no=CTE0.admim_no
where CTE0.rn=1
结果如
Anthony Tee Tony 1000 MockExams2014 Chemistry PP1 12 D+ 1 Biology PP1 50 C+ NULL NULL NULL NULL
Moses K Ndu NULL 1001 MockExams2014 Chemistry PP1 65 B+ 1 Biology PP1 85 A Physiks PP2 12 D+
最初提到的outpu的一列更简单的方法(2)如下所示:
Declare @a table (FirstName varchar(50) ,LastName varchar(50),OtherName varchar(50), admim_no int,ExamCategory varchar(50), subject varchar(50), Exam Varchar(50), Score int,grade varchar(50))
Insert into @a Values ('Anthony','Tee','Tony',1000 ,' MockExams2014','Chemistry','PP1',12,'D+')
Insert into @a Values ('Anthony','Tee','Tony',1000 ,' MockExams2014','Biology','PP1',50,'C+')
Insert into @a Values ('Moses K','Ndu',NULL,1001 ,' MockExams2014','Chemistry','PP1',65,'B+')
Insert into @a Values ('Moses K','Ndu',NULL,1001 ,' MockExams2014','Biology','PP1',85,'A')
Insert into @a Values ('Moses K','Ndu',NULL,1001 ,' MockExams2014','Physiks','PP1',12,'D+')
Select FirstName,LastName,OtherName,admim_no,ExamCategory
, STUFF(
(SELECT ',' + subject +', ' + Exam +', ' + CAST(Score as varchar(20)) + ', ' + Grade
FROM @a a2 where a1.admim_no = a2.admim_no
FOR XML PATH (''))
, 1, 1, '') as subjectExamScoreGrade
from @a a1
Group by FirstName,LastName,OtherName,admim_no,ExamCategory