我有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功能非常具体,另一个问题没有回答我的问题。
答案 0 :(得分:7)
由于您使用的是SQL Server 2008,因此可以使用PIVOT
函数来获取结果。此函数将通过使用聚合函数将您的数据行转换为列。由于您的数据是字符串,因此您只能使用max
或min
汇总函数。
如果您的列数有限,则可以对查询进行硬编码。基本语法为:
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来生成结果。这将创建您希望在最终结果中具有的问题列表,并且您将创建将要执行的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) |