从两个表中选择,将一个表中的行转换为列

时间:2017-02-01 19:45:52

标签: sql sql-server

我正在尝试将数据导出为CSV,并且需要将第二个表中的多个列转换为行。要启动,我在第二个表中没有固定数量的行,但需要在导出中使用固定数量的字段。这是我的数据样本(我希望它能解决我的问题)。数据加入StudentID。使用MS SQL Server 2014。

用户表

StudentID | Last Name | First Name | Middle Name/Initial | Is Active | Grade | School Name 
___________________________________________________________________________________________
1         | Pinciati  | Donna      | J                   | Y         | 10    | High        
2         | Hyde      | Steven     | K                   | Y         | 11    | Middle      
3         | Foreman   | Eric       | L                   | Y         | 10    | High        
4         | Kelso     | Michael    | G                   | Y         | 11    | High        

警报表

ID | StudentID | Alert Type       | Alert Comments
___________________________________________________
1  | 2         | Asthma           | NULL
2  | 2         | Allergy          | Bee Sting
3  | 3         | Allergy          | Peanut
4  | 4         | Medial Equipment | Crutches
5  | 4         | Allergy          | Bee Sting

我的结果集需要如下所示:

StudentID | Last Name | First Name | Middle Name/Initial | Is Active | Grade | School Name | Alert Type 1     | Alert Comments 1 | Alert Type 2 | Alert Comments 2 | Alert Type 3 | Alert Comments 3    
1         | Pinciati  | Donna      | J                   | Y         | 10    | High        | NULL             | NULL             | NULL         | NULL             | NULL         | NULL
2         | Hyde      | Steven     | K                   | Y         | 11    | Middle      | Asthma           | NULL             | Allergy      | Bee Sting        | NULL         | NULL
3         | Foreman   | Eric       | L                   | Y         | 10    | High        | Allergy          | Peanut           | NULL         | NULL             | NULL         | NULL
4         | Kelso     | Michael    | G                   | Y         | 11    | High        | Medial Equipment | Crutches         | Allergy      | Bee Sting        | NULL         | NULL

我知道我的警报比我的数据更多,但模板中有固定数量的字段我无法更改,因此即使它们为NULL,我也必须填写所有警报字段。
帮助我Obi-Wan Kenobi;你是我唯一的希望!

2 个答案:

答案 0 :(得分:1)

使用子查询或 common table expression row_number() ,您可以在StudentId上保持联接并根据该行进行汇总号码(rn)。

select
    s.StudentID 
  , s.LastName  
  , s.FirstName 
  , s.MiddleName
  , s.IsActive  
  , s.Grade     
  , s.SchoolName
  , AlertType_1     = max(case when rn = 1 then al.AlertType else null end)
  , AlertComments_1 = max(case when rn = 1 then al.AlertComments else null end)
  , AlertType_2     = max(case when rn = 2 then al.AlertType else null end)
  , AlertComments_2 = max(case when rn = 2 then al.AlertComments else null end)
  , AlertType_3     = max(case when rn = 3 then al.AlertType else null end)
  , AlertComments_3 = max(case when rn = 3 then al.AlertComments else null end)
  from dbo.student as s
    left join (
      select StudentId, AlertType, AlertComments
        , rn = row_number() over (
            partition by StudentId
            order by AlertType, AlertComments
          )
       from dbo.Alert
    ) as al on s.StudentId = al.StudentId 
  group by 
    s.StudentID 
  , s.LastName  
  , s.FirstName 
  , s.MiddleName
  , s.IsActive  
  , s.Grade     
  , s.SchoolName

rextester:http://rextester.com/YMDQI47779

测试设置:

create table Student  (
    StudentID    int
  , LastName   nvarchar(32)
  , FirstName  nvarchar(32)
  , MiddleName nvarchar(32)
  , IsActive   char(1)
  , Grade      int
  , SchoolName nvarchar(32)
  ); 
insert into dbo.Student values
 (1,'Pinciati','Donna','J','Y',10,'High')
,(2,'Hyde','Steven','K','Y',11,'Middle')
,(3,'Foreman','Eric','L','Y',10,'High')
,(4,'Kelso','Michael','G','Y',11,'High');

create table dbo.Alert (
    ID            int
  , StudentID     int
  , AlertType     nvarchar(64)
  , AlertComments nvarchar(64)
);
insert into dbo.Alert values
 (1,2,'Asthma','NULL')
,(2,2,'Allergy','Bee Sting')
,(3,3,'Allergy','Peanut')
,(4,4,'Medial Equipment','Crutches')
,(5,4,'Allergy','Bee Sting');

查询:

;with al as (
  select StudentId, AlertType, AlertComments
    , rn = row_number() over (
      partition by StudentId
      order by AlertType, AlertComments
      )
from dbo.Alert
)
select
    s.StudentID 
  , s.LastName  
  , s.FirstName 
  , s.MiddleName
  , s.IsActive  
  , s.Grade     
  , s.SchoolName
  , AlertType_1     = max(case when rn = 1 then al.AlertType else null end)
  , AlertComments_1 = max(case when rn = 1 then al.AlertComments else null end)
  , AlertType_2     = max(case when rn = 2 then al.AlertType else null end)
  , AlertComments_2 = max(case when rn = 2 then al.AlertComments else null end)
  , AlertType_3     = max(case when rn = 3 then al.AlertType else null end)
  , AlertComments_3 = max(case when rn = 3 then al.AlertComments else null end)
  from dbo.student as s
    left join al on s.StudentId = al.StudentId 
  group by 
    s.StudentID 
  , s.LastName  
  , s.FirstName 
  , s.MiddleName
  , s.IsActive  
  , s.Grade     
  , s.SchoolName

结果:

+-----------+----------+-----------+------------+----------+-------+------------+-------------+-----------------+------------------+-----------------+-------------+-----------------+
| StudentID | LastName | FirstName | MiddleName | IsActive | Grade | SchoolName | AlertType_1 | AlertComments_1 |   AlertType_2    | AlertComments_2 | AlertType_3 | AlertComments_3 |
+-----------+----------+-----------+------------+----------+-------+------------+-------------+-----------------+------------------+-----------------+-------------+-----------------+
|         1 | Pinciati | Donna     | J          | Y        |    10 | High       | NULL        | NULL            | NULL             | NULL            | NULL        | NULL            |
|         2 | Hyde     | Steven    | K          | Y        |    11 | Middle     | Allergy     | Bee Sting       | Asthma           | NULL            | NULL        | NULL            |
|         3 | Foreman  | Eric      | L          | Y        |    10 | High       | Allergy     | Peanut          | NULL             | NULL            | NULL        | NULL            |
|         4 | Kelso    | Michael   | G          | Y        |    11 | High       | Allergy     | Bee Sting       | Medial Equipment | Crutches        | NULL        | NULL            |
+-----------+----------+-----------+------------+----------+-------+------------+-------------+-----------------+------------------+-----------------+-------------+-----------------+

答案 1 :(得分:0)

试试这个:

with alert as (
select f0.*, 
row_number() over(partition by f0.studientID order by f0.ID) rang from Alert_TAble f0
)
select f0.*, 
       f1.AlertType as AlertType1, f1.AlertComment as AlertComment1,
       f2.AlertType as AlertType2, f2.AlertComment as AlertComment2, 
       f3.AlertType as AlertType3, f3.AlertComment as AlertComment3  
from User_Table f0
left outer join alert f1 on f0.studientID=f1.studientID and f1.rang=1
left outer join alert f2 on f0.studientID=f2.studientID and f2.rang=2
left outer join alert f3 on f0.studientID=f3.studientID and f3.rang=3