转换SQL查询结果

时间:2011-03-26 06:42:49

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

我需要获取一些查询结果并将其展平以获得报告。

DECLARE @randomTable table (ID int, OtherID int, Val varchar(max))

insert into @randomTable(ID, OtherID, Val)
values (1, 100, 'Some Value 1'), (2, 100, 'Some Other 2'),
       (3, 100, 'Some Value 3'), (4, 200, 'Some Other 4'),
       (5, 200, 'Some Value 5'), (6, 300, 'Some Other 6'),
       (7, 300, 'Some Value 7'), (8, 300, 'Some Other 8'),
       (9, 400, 'Some Value 9'), (10, 500, 'Some Other 10')            

select OtherID, Val from @randomTable

结果:

--  100 | Some Value 1
--  100 | Some Other 2
--  100 | Some Value 3
--  200 | Some Other 4
--  200 | Some Value 5
--  300 | Some Other 6
--  300 | Some Value 7
--  300 | Some Other 8
--  400 | Some Value 9
--  500 | Some Other 10

是否有SQL方法可以将其更改为选择:

--  100 | Some Value 1 | Some Other 2 | Some Value 3
--  200 | Some Other 4 | Some Value 5
--  300 | Some Other 6 | Some Value 7 | Some Other 8
--  400 | Some Value 9
--  500 | Some Other 10

注意:以上是一个例子。我的真实数据不是静态的。此外,在我的实际数据中,OtherID是字符串值,Val值是存储为varbinary的图像。

我当然要限制我允许的列数。我想最多5个(之后我可以丢失额外的行)。

有没有办法做到这一点?

3 个答案:

答案 0 :(得分:4)

;WITH cte
     AS (SELECT OtherID,
                Val,
                ROW_NUMBER() OVER (PARTITION BY OtherID ORDER BY (SELECT 0)) rn
         FROM   @randomTable)
SELECT OtherID,
       [1],
       [2],
       [3],
       [4],
       [5]
FROM   cte PIVOT( MAX(Val) FOR rn IN ([1], [2], [3], [4], [5])) AS PivotTable;  

要提供一些解释,SELECT * FROM cte会返回以下内容。

OtherID     Val                  rn
----------- -------------------- ---
100         Some Value 1         1
100         Some Other 2         2
100         Some Value 3         3
200         Some Other 4         1
200         Some Value 5         2
300         Some Other 6         1
300         Some Value 7         2
300         Some Other 8         3
400         Some Value 9         1
500         Some Other 10        1

我添加了row_number列,以便在PIVOT中提供一些内容。请注意,每个OtherID,rn组合有一行或一行。 PIVOT语句等同于以下内容。

SELECT OtherID,
       MAX(CASE WHEN rn=1 THEN Val END) AS [1],
       MAX(CASE WHEN rn=2 THEN Val END) AS [2],
       MAX(CASE WHEN rn=3 THEN Val END) AS [3],
       MAX(CASE WHEN rn=4 THEN Val END) AS [4],
       MAX(CASE WHEN rn=5 THEN Val END) AS [5]
FROM cte
GROUP BY OtherID /*You want one row per OtherID */

答案 1 :(得分:2)

我不确定您是要转入列还是将结果连接到一个列(用于报告)。

如果您正在寻找动态支点,请查看此处的文章:link及其后续评论。如果您能够限制数据透视中涉及的列,则可以使用数据透视运算符(如前所述)并获得更好的性能。

如果您希望将行连接到列,请查看以下查询。利用XML PATH确实会对特殊字符(<& etc.等)产生一些影响,因此如果这适用于您的情况,请回发一下,我们可以扩展这个简单的示例。

 -- if you have normalized type table use it instead of this cte
    ;with   c_distinct (OtherId) 
    as      (   select  distinct OtherId 
                from    @randomTable
            )
    select  OtherId,
            stuff(c, 1, 2, '') 
    from    c_distinct cd
    cross
    apply   (   select  '| ' + Val
                from    @randomTable rt
                where   cd.OtherId = rt.OtherId
                for xml path('')
            ) d(c)

答案 2 :(得分:0)

你要求的是非规范化,对吧?

我认为你的问题在这里得到解答:Denormalizing Data (Maybe A Pivot?)