我有两个表格,其结构与此类似:
人:
ID Name Age
1 Jack 25
2 Jill 23
试验:
ID PersonID TestID Result
1 1 1 125
2 1 2 120
3 1 3 75
4 2 1 90
5 2 2 95
6 2 3 7.2
有没有办法使用单个语句检索数据,方法是主表中的每个记录都显示在一行中?像这样:
PersonID Name Age Test1 Test2 Test3
1 Jack 25 125 120 75
2 Jill 23 90 95 7.2
到目前为止,我提出的唯一方法是创建一个迭代详细记录并填充临时表的函数。不是很优雅。
提前致谢
答案 0 :(得分:2)
要获得此结果,您需要使用PIVOT
功能。这会将多行数据转换为列。
如果您提前知道这些值,或者您的TestId
值的数量有限,那么您可以对查询进行硬编码,使查询保持静态。
SELECT Name,
Age,
[1] AS Test1,
[2] AS Test2,
[3] AS Test3
FROM
(
SELECT P.Name, P.Age, t.TestID, t.Result
FROM tests t
INNER JOIN person P
ON p.ID = t.PersonID
) T
PIVOT
(
sum(Result)
FOR TestID IN ([1], [2], [3])
) piv;
但是如果您有TestId
个未知数量的值,那么您将需要使用动态SQL在运行时生成列列表。您的代码将是:
DECLARE @cols AS NVARCHAR(MAX),
@colNames AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(testId)
from tests
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colNames = STUFF((SELECT distinct ',' + QUOTENAME(testId) +' as Test'+cast(testId as varchar(10))
from tests
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT Name, age, ' + @colnames + ' from
(
select P.Name, P.Age, t.TestID, t.Result
from tests t
inner join person P
on p.ID = t.PersonID
) x
pivot
(
sum(Result)
for TestID in (' + @cols + ')
) p '
execute(@query)
它们都将产生相同的结果,不同之处在于,如果测试ID的数量发生变化,动态的将增加/减少列:
| NAME | AGE | TEST1 | TEST2 | TEST3 |
--------------------------------------
| Jack | 25 | 125 | 120 | 75 |
| Jill | 23 | 90 | 95 | 7.2 |
答案 1 :(得分:1)
您可以在TestID上进行转轴
你去......它有点乱,但你可以改进它:)
SELECT Name,Age,SUM([1]) AS Test1,SUM([2]) AS Test2,SUM([3]) AS Test3
FROM(
SELECT P.Name,P.Age,Te.ID, TestID,Result
FROM Test Te
INNER JOIN dbo.Person P ON P.ID=Te.PersonID) T
PIVOT(MAX(T.Result) FOR TestID IN([1],[2],[3])) AS pvt
GROUP BY Name,Age
继承人一些链接
http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx http://www.codeproject.com/Questions/393632/How-to-use-Pivot-in-SQL http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/