2

我有两个结构类似于此的表:

人:

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

到目前为止,我想出的唯一方法是创建一个迭代详细记录并填充临时表的函数。不是很优雅。

提前致谢

4

2 回答 2

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;

请参阅SQL Fiddle with Demo

但是,如果您有未知数量的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)

请参阅SQL Fiddle with Demo

它们都将产生相同的结果,不同之处在于如果测试 id 的数量发生变化,动态的将增加/减少列:

| NAME | AGE | TEST1 | TEST2 | TEST3 |
--------------------------------------
| Jack |  25 |   125 |   120 |    75 |
| Jill |  23 |    90 |    95 |   7.2 |
于 2013-02-09T16:21:37.330 回答
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/

于 2013-02-09T09:02:24.220 回答