数据透视表SQL

时间:2014-01-13 13:43:50

标签: sql sql-server sql-server-2008 pivot

我有3张桌子。

1 - 学生

| student_code |  name   |  
--------------------------
| 1            |  katia  |   
| 2            |  roger  |   
| 3            |  ken    | 

2 - 问题

| question_code|  question       |  
----------------------------------
| 1            |  father' name   |   
| 2            |  favorite fruit |   
| 3            |  first teacher  | 

3 - 答案

| student_code | question_code | answer  |  
-------------------------------------------
| 1            | 1             |  katia  |    
| 1            | 2             |  banana |   
| 2            | 1             |   ken   | 

当我加入这个3时,我有800.000行像这样:

| name  | question        | answer  |  
-------------------------------------
| katia| favorite fruit   |  banana |   
| katia| father's name    |  paul   |   
| roger| father's name    |  aaron  | 

我需要转换列的问题行,每行只维持1名学生。

我搜索了数据透视表,但我无法使其有效。

OBS:并非每个学生都有所有问题

编辑:我认为这个问题没有重复,因为PIVOT功能非常具体,另一个问题没有回答我的问题。

1 个答案:

答案 0 :(得分:7)

由于您使用的是SQL Server 2008,因此可以使用PIVOT函数来获取结果。此函数将通过使用聚合函数将您的数据行转换为列。由于您的数据是字符串,因此您只能使用maxmin汇总函数。

如果您的列数有限,则可以对查询进行硬编码。基本语法为:

select name,
  [father' name], 
  [favorite fruit],
  [first teacher]
from
(
  select q.question,
    a.answer,
    s.name
  from student s
  left join answers a
    on s.student_code = a.student_code
  left join question q
    on a.question_code = q.question_code 
) d
pivot
(
  max(answer)
  for question in ([father' name], [favorite fruit],
                   [first teacher])
) piv;

SQL Fiddle with Demo

但是如果您的问题数量不明,那么您将需要使用动态SQL来生成结果。这将创建您希望在最终结果中具有的问题列表,并且您将创建将要执行的sql字符串。代码类似于:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(question) 
                    from question
                    group by question_code, question
                    order by question_code
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = N'SELECT name, ' + @cols + N' 
            from 
            (
              select q.question,
                a.answer,
                s.name
              from student s
              left join answers a
                on s.student_code = a.student_code
              left join question q
                on a.question_code = q.question_code 
            ) x
            pivot 
            (
                max(answer)
                for question in (' + @cols + N')
            ) p '

execute sp_executesql @query;

SQL Fiddle with Demo。两者都会给出结果:

|  NAME | FATHER' NAME | FAVORITE FRUIT | FIRST TEACHER |
|-------|--------------|----------------|---------------|
| katia |        katia |         banana |        (null) |
|   ken |       (null) |         (null) |        (null) |
| roger |          ken |         (null) |        (null) |