Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 SQL Server 2008-透视表_Sql Server 2008_Pivot_Pivot Table - Fatal编程技术网

Sql server 2008 SQL Server 2008-透视表

Sql server 2008 SQL Server 2008-透视表,sql-server-2008,pivot,pivot-table,Sql Server 2008,Pivot,Pivot Table,我正在尝试对我的表进行透视,以将行作为列输出。 我在网上看到了一些例子,但每次解释到否定时,我都会迷路(我认为这与我想要实现的目标无关?)。我有下面的课程表: StudentID ClassCode 10001 ENG240 10001 MTH100 10001 BIO101 10001 HUM300 10002 PHY200 10002 PHY200-L 1000

我正在尝试对我的表进行透视,以将行作为列输出。 我在网上看到了一些例子,但每次解释到否定时,我都会迷路(我认为这与我想要实现的目标无关?)。我有下面的课程表:

StudentID       ClassCode
10001           ENG240
10001           MTH100
10001           BIO101
10001           HUM300
10002           PHY200
10002           PHY200-L
10002           MTH100
10002           HUM200
10002           CHR100
10002           COM140
10003           HUM100
10003           ENG200
10003           PHY101
我想要得到的是以下输出:

StudentID       ClassCode 1     ClassCode 2     ClassCode 3     ClassCode 4     ClassCode 5
10001           ENG240          MTH100          BIO101          HUM300
10002           PHY200          PHY200-L        MTH100          HUM200          CHR100
10002           COM140
10003           HUM100          ENG200          PHY101    
pivot字段最多只能有五列。如果有学生有五个以上的课程,则应向结果集中添加新记录

有谁能告诉我一个实现这一目标的好方法吗? 太多了

*编辑:*

现在,我可以使用下面的查询透视表:

CREATE 
  TABLE  #TestClass 
         (StudentID INT, row INT, ClassCode VARCHAR(32))


  ;WITH  TCSPivot(StudentID, row, ClassCode)
     AS
        (SELECT  StudentID,
                 row_number() OVER(PARTITION BY StudentID ORDER BY StudentID, ClassCode),
                 ClassCode
           FROM  student_class
         )

 INSERT 
   INTO  #TestClass
 SELECT  p.StudentID, 
         p.row, 
         p.ClassCode
   FROM  MyPivot p
   JOIN  class c
     ON  c.ClassCode   = p.ClassCode


    SELECT  @sql = @sql + ', MAX(CASE WHEN row = ' + CAST(tc.row AS CHAR(5)) + ' THEN ClassCode ELSE '''' END) AS [ClassCode ' + CAST(tc.row AS CHAR(5)) + ']'
       FROM  #TestClass tc 
      GROUP 
         BY  tc.row
      ORDER  
         BY  tc.row

        SET  @sql = @sql + N' 
                            FROM  #TestClass
                           GROUP 
                              BY  StudentID
                           ORDER 
                              BY  StudentID'

       EXEC  sp_executesql @sql
我现在需要做的是如何限制只有5条记录应该垂直旋转。如果学生的班级超过5个,则应添加第二个记录


谢谢大家

通过实现两个窗口函数,
ntile()
row\u number()
,您可以轻松获得结果

将用于将您的数据划分为“bucket”,因此当您使用
NTILE(5)
时,您将为每个
StudentId
classcode
创建5个bucket

select StudentId, ClassCode,
  newCol =
   'ClassCode' +
      cast(ntile(5) over(partition by StudentId 
                         order by ClassCode) as varchar(1))
from TestClass;
看。这会将您的数据转换为以下格式:

| STUDENTID | CLASSCODE |     NEWCOL |
|-----------|-----------|------------|
|     10002 |    CHR100 | ClassCode1 |
|     10002 |    COM140 | ClassCode1 |
|     10002 |    HUM200 | ClassCode2 |
|     10002 |    MTH100 | ClassCode3 |
|     10002 |    PHY200 | ClassCode4 |
|     10002 |  PHY200-L | ClassCode5 |
正如您可以看到的,数据现在在5个存储桶中,这些存储桶是您的新列名
ClassCode1
ClassCode2
,等等。您还将注意到有两行
ClassCode1
,如果现在应用PIVOT函数,您将只返回一行。为了返回多行,您需要对数据应用
row\u number()

行编号()
将为每行数据创建一个唯一的序列:

;with cte as
(
  select StudentId, ClassCode,
    newCol =
      'ClassCode' +
        cast(ntile(5) over(partition by StudentId 
                           order by ClassCode) as varchar(1))
  from TestClass
),
mr as
(
  select StudentId, ClassCode,
    newCol,
    row_number() over(partition by StudentId, newCol order by newCol) seq
  from cte
)
select *
from mr;
看。这将得到以下结果:

| STUDENTID | CLASSCODE |     NEWCOL | SEQ |
|-----------|-----------|------------|-----|
|     10002 |    CHR100 | ClassCode1 |   1 |
|     10002 |    COM140 | ClassCode1 |   2 |
|     10002 |    HUM200 | ClassCode2 |   1 |
|     10002 |    MTH100 | ClassCode3 |   1 |
|     10002 |    PHY200 | ClassCode4 |   1 |
|     10002 |  PHY200-L | ClassCode5 |   1 |
| STUDENTID | CLASSCODE1 | CLASSCODE2 | CLASSCODE3 | CLASSCODE4 | CLASSCODE5 |
|-----------|------------|------------|------------|------------|------------|
|     10001 |     BIO101 |     ENG240 |     HUM300 |     MTH100 |     (null) |
|     10002 |     CHR100 |     HUM200 |     MTH100 |     PHY200 |   PHY200-L |
|     10002 |     COM140 |     (null) |     (null) |     (null) |     (null) |
|     10003 |     ENG200 |     HUM100 |     PHY101 |     (null) |     (null) |
相同的
ClassCode1
值现在具有不同的序列号。在数据透视过程中按数据分组时,需要使用此选项

最后,您可以应用
PIVOT
函数来获得最终结果:

;with cte as
(
  select StudentId, ClassCode,
    newCol =
      'ClassCode' +
        cast(ntile(5) over(partition by StudentId 
                           order by ClassCode) as varchar(1))
  from TestClass
),
mr as
(
  select StudentId, ClassCode,
    newCol,
    row_number() over(partition by StudentId, newCol order by newCol) seq
  from cte
)
select studentid,
  ClassCode1, ClassCode2, ClassCode3, 
  ClassCode4, ClassCode5
from  mr
pivot
(
  max(ClassCode)
  for NewCol in (ClassCode1, ClassCode2, ClassCode3, 
                 ClassCode4, ClassCode5)
) piv
order by StudentId;

如果您想使用聚合函数和您在问题中遇到的CASE表达式,那么您仍然可以使用
NTILE()
row\u number()
,但最终的代码是:

;with cte as
(
  select StudentId, ClassCode,
    newCol =
      'ClassCode' +
        cast(ntile(5) over(partition by StudentId 
                           order by ClassCode) as varchar(1))
  from TestClass
),
mr as
(
  select StudentId, ClassCode,
    newCol,
    row_number() over(partition by StudentId, newCol order by newCol) seq
  from cte
)
select studentid,
  max(case when newcol = 'ClassCode1' then ClassCode end) ClassCode1,
  max(case when newcol = 'ClassCode2' then ClassCode end) ClassCode2,
  max(case when newcol = 'ClassCode3' then ClassCode end) ClassCode3,
  max(case when newcol = 'ClassCode4' then ClassCode end) ClassCode4,
  max(case when newcol = 'ClassCode5' then ClassCode end) ClassCode5
from  mr
group by StudentId, seq
order by StudentId;
看。两个版本都将给出以下最终结果:

| STUDENTID | CLASSCODE |     NEWCOL | SEQ |
|-----------|-----------|------------|-----|
|     10002 |    CHR100 | ClassCode1 |   1 |
|     10002 |    COM140 | ClassCode1 |   2 |
|     10002 |    HUM200 | ClassCode2 |   1 |
|     10002 |    MTH100 | ClassCode3 |   1 |
|     10002 |    PHY200 | ClassCode4 |   1 |
|     10002 |  PHY200-L | ClassCode5 |   1 |
| STUDENTID | CLASSCODE1 | CLASSCODE2 | CLASSCODE3 | CLASSCODE4 | CLASSCODE5 |
|-----------|------------|------------|------------|------------|------------|
|     10001 |     BIO101 |     ENG240 |     HUM300 |     MTH100 |     (null) |
|     10002 |     CHR100 |     HUM200 |     MTH100 |     PHY200 |   PHY200-L |
|     10002 |     COM140 |     (null) |     (null) |     (null) |     (null) |
|     10003 |     ENG200 |     HUM100 |     PHY101 |     (null) |     (null) |

由于只有5列,因此不需要使用动态SQL来获得结果。

通过实现两个窗口函数,
ntile()
row\u number()
可以轻松获得结果

将用于将您的数据划分为“bucket”,因此当您使用
NTILE(5)
时,您将为每个
StudentId
classcode
创建5个bucket

select StudentId, ClassCode,
  newCol =
   'ClassCode' +
      cast(ntile(5) over(partition by StudentId 
                         order by ClassCode) as varchar(1))
from TestClass;
看。这会将您的数据转换为以下格式:

| STUDENTID | CLASSCODE |     NEWCOL |
|-----------|-----------|------------|
|     10002 |    CHR100 | ClassCode1 |
|     10002 |    COM140 | ClassCode1 |
|     10002 |    HUM200 | ClassCode2 |
|     10002 |    MTH100 | ClassCode3 |
|     10002 |    PHY200 | ClassCode4 |
|     10002 |  PHY200-L | ClassCode5 |
正如您可以看到的,数据现在在5个存储桶中,这些存储桶是您的新列名
ClassCode1
ClassCode2
,等等。您还将注意到有两行
ClassCode1
,如果现在应用PIVOT函数,您将只返回一行。为了返回多行,您需要对数据应用
row\u number()

行编号()
将为每行数据创建一个唯一的序列:

;with cte as
(
  select StudentId, ClassCode,
    newCol =
      'ClassCode' +
        cast(ntile(5) over(partition by StudentId 
                           order by ClassCode) as varchar(1))
  from TestClass
),
mr as
(
  select StudentId, ClassCode,
    newCol,
    row_number() over(partition by StudentId, newCol order by newCol) seq
  from cte
)
select *
from mr;
看。这将得到以下结果:

| STUDENTID | CLASSCODE |     NEWCOL | SEQ |
|-----------|-----------|------------|-----|
|     10002 |    CHR100 | ClassCode1 |   1 |
|     10002 |    COM140 | ClassCode1 |   2 |
|     10002 |    HUM200 | ClassCode2 |   1 |
|     10002 |    MTH100 | ClassCode3 |   1 |
|     10002 |    PHY200 | ClassCode4 |   1 |
|     10002 |  PHY200-L | ClassCode5 |   1 |
| STUDENTID | CLASSCODE1 | CLASSCODE2 | CLASSCODE3 | CLASSCODE4 | CLASSCODE5 |
|-----------|------------|------------|------------|------------|------------|
|     10001 |     BIO101 |     ENG240 |     HUM300 |     MTH100 |     (null) |
|     10002 |     CHR100 |     HUM200 |     MTH100 |     PHY200 |   PHY200-L |
|     10002 |     COM140 |     (null) |     (null) |     (null) |     (null) |
|     10003 |     ENG200 |     HUM100 |     PHY101 |     (null) |     (null) |
相同的
ClassCode1
值现在具有不同的序列号。在数据透视过程中按数据分组时,需要使用此选项

最后,您可以应用
PIVOT
函数来获得最终结果:

;with cte as
(
  select StudentId, ClassCode,
    newCol =
      'ClassCode' +
        cast(ntile(5) over(partition by StudentId 
                           order by ClassCode) as varchar(1))
  from TestClass
),
mr as
(
  select StudentId, ClassCode,
    newCol,
    row_number() over(partition by StudentId, newCol order by newCol) seq
  from cte
)
select studentid,
  ClassCode1, ClassCode2, ClassCode3, 
  ClassCode4, ClassCode5
from  mr
pivot
(
  max(ClassCode)
  for NewCol in (ClassCode1, ClassCode2, ClassCode3, 
                 ClassCode4, ClassCode5)
) piv
order by StudentId;

如果您想使用聚合函数和您在问题中遇到的CASE表达式,那么您仍然可以使用
NTILE()
row\u number()
,但最终的代码是:

;with cte as
(
  select StudentId, ClassCode,
    newCol =
      'ClassCode' +
        cast(ntile(5) over(partition by StudentId 
                           order by ClassCode) as varchar(1))
  from TestClass
),
mr as
(
  select StudentId, ClassCode,
    newCol,
    row_number() over(partition by StudentId, newCol order by newCol) seq
  from cte
)
select studentid,
  max(case when newcol = 'ClassCode1' then ClassCode end) ClassCode1,
  max(case when newcol = 'ClassCode2' then ClassCode end) ClassCode2,
  max(case when newcol = 'ClassCode3' then ClassCode end) ClassCode3,
  max(case when newcol = 'ClassCode4' then ClassCode end) ClassCode4,
  max(case when newcol = 'ClassCode5' then ClassCode end) ClassCode5
from  mr
group by StudentId, seq
order by StudentId;
看。两个版本都将给出以下最终结果:

| STUDENTID | CLASSCODE |     NEWCOL | SEQ |
|-----------|-----------|------------|-----|
|     10002 |    CHR100 | ClassCode1 |   1 |
|     10002 |    COM140 | ClassCode1 |   2 |
|     10002 |    HUM200 | ClassCode2 |   1 |
|     10002 |    MTH100 | ClassCode3 |   1 |
|     10002 |    PHY200 | ClassCode4 |   1 |
|     10002 |  PHY200-L | ClassCode5 |   1 |
| STUDENTID | CLASSCODE1 | CLASSCODE2 | CLASSCODE3 | CLASSCODE4 | CLASSCODE5 |
|-----------|------------|------------|------------|------------|------------|
|     10001 |     BIO101 |     ENG240 |     HUM300 |     MTH100 |     (null) |
|     10002 |     CHR100 |     HUM200 |     MTH100 |     PHY200 |   PHY200-L |
|     10002 |     COM140 |     (null) |     (null) |     (null) |     (null) |
|     10003 |     ENG200 |     HUM100 |     PHY101 |     (null) |     (null) |

由于您只有5列,因此不需要使用动态SQL来获得结果。

到目前为止您尝试了什么,以及将类代码放在ClassCode1、2、3下的逻辑是什么???你好这是我需要输出的报告。基本上,客户机需要的是一个在页面上垂直显示类的报告。到目前为止,我已经能够做到这一点。但是,我仍然需要关于如何将最大列设置为5以及如何在类超过5的情况下创建另一行记录的帮助。请看我的编辑上面。非常感谢。到目前为止,您尝试了什么?将类代码放在ClassCode1、2、3…下的逻辑是什么???你好这是我需要输出的报告。基本上,客户机需要的是一个在页面上垂直显示类的报告。到目前为止,我已经能够做到这一点。但是,我仍然需要关于如何将最大列设置为5以及如何在类超过5的情况下创建另一行记录的帮助。请看我的编辑上面。非常感谢。你好非常感谢这个!!!我有一个快速跟进的问题。如果我决定添加另一个名为SectionCode的列,该列与类代码有一定的1:1对应关系,该怎么办?这会如何影响表的轴呢?我能够使用
NTILE()
函数输出带有类代码的SectionCode。但我有点迷路了。非常感谢你!!!!没关系,我可以通过调整你的代码使它工作!非常感谢!19小时后给你赏金。(由于某些原因,系统现在不允许我授予它)非常感谢!!!!!!!!!!!!!!!!你好非常感谢这个!!!我有一个快速跟进的问题。如果我决定添加另一个名为SectionCode的列,该列与类代码有一定的1:1对应关系,该怎么办?这会如何影响表的轴呢?我能够使用
NTILE()
函数输出带有类代码的SectionCode。但我有点迷路了。非常感谢你!!!!没关系,我可以通过调整你的代码使它工作!谢谢