将查询转换为列的组合

时间:2012-06-05 19:21:48

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

在Sql Server 2008中,如何从这里开始:

Owner  Animal   Age  Height   Weight  
-----  ------   ---  ------   ------ 
Steve  Dog        8     22      60 
Steve  Cat        5     11      14 
Steve  Gerbil     2     1.5     0.3  

到这里:

Owner  Dog_Age  Dog_Height  Dog_Weight  Cat_Age  Cat_Height  ...
-----  -------  ----------  ----------  -------  ----------  ...
Steve       8           22          60        5          11  ...   

所以我正在转动Animal列,但想要为动物和某些列的所有可能组合生成列。实际上没有执行聚合函数。因为对于我的表格,可能的组合总数会相当大,我想要一个避免我必须明确输入每个结果列名称的解决方案,但是如果必须的话,我会这样做。

我已经看了几个PIVOT命令的例子,但是我没有遇到过像上面这样的组合创建列的任何例子,所以我不确定这是否可行。 SQL Server不是我的专业领域。

1 个答案:

答案 0 :(得分:1)

如果您不关心最终输出中列的顺序:

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = N'';

SELECT 
    @sql = @sql + ',' + Animal + '_$c$ = MAX(CASE WHEN Animal = ''' 
          + Animal + ''' THEN $c$ END)'
FROM dbo.PetStuff
GROUP BY Animal;

SELECT @sql = 'SELECT Owner '
 + REPLACE(@sql, '$c$', 'Age')
 + REPLACE(@sql, '$c$', 'Height')
 + REPLACE(@sql, '$c$', 'Weight')
 + ' FROM dbo.PetStuff
 GROUP BY Owner;';

PRINT @sql;
-- EXEC sp_executesql @sql;

如果列顺序很重要(按动物名称排序,则按字母顺序排列年龄/身高/体重),那么您可以将列放在表格中,然后生成稍微多一点的SQL:

DECLARE @cols TABLE(col SYSNAME);
INSERT @cols SELECT 'Age' UNION ALL SELECT 'Weight' UNION ALL SELECT 'Height';

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = N'';

SELECT @sql = @sql + ',' + p.Animal + '_' + col 
  + ' = MAX(CASE WHEN Animal = ''' 
  + p.Animal + ''' THEN ' + c.col + ' END)'
FROM dbo.PetStuff AS p
CROSS APPLY @cols AS c
GROUP BY p.Animal, c.col
ORDER BY p.Animal, c.col;

SELECT @sql = 'SELECT Owner ' + @sql
 + ' FROM dbo.PetStuff
 GROUP BY Owner;';

PRINT @sql;
-- EXEC sp_executesql @sql;

如果没有动态SQL,无法想到任何方法。