执行数据透视但不聚合的T-SQL查询

时间:2013-01-24 07:26:01

标签: sql tsql pivot

您好我有以下数据表

Class | Member | Value
----------------------
c1    | m1     | 10
c1    | m2     | 20
c1    | list   | 30
c1    | list   | 40
c1    | list   | 50
c2    | m1     | 60
c2    | m2     | 70
c2    | list   | 80

并希望将数据转换为此表单

Class | Member 1 | Member 2 | List
----------------------------------
c1    | 10       | 20       | 30
c1    | 10       | 20       | 40
c1    | 10       | 20       | 50
c2    | 60       | 70       | 80

使用max的正常枢轴作为聚合函数会给我

Class | Member 1 | Member 2 | List
----------------------------------
c1    | 10       | 20       | 50
c2    | 60       | 70       | 80

但我希望列出任何Class的每个List值。

而不是通过编写充满CASE的SQL查询来找到替代方案,例如CASE成员WHEN'm1'然后是Value,CASE成员WHEN'm2'然后是Value,...为了达到我想要的目的,我想知道是否有任何有机会使用枢轴进行一些调整,使其适合我的任务吗?

数据库是SQL 2008 R2

谢谢

2 个答案:

答案 0 :(得分:2)

没有。 PIVOT实际上是用于围绕CASE表达式进行聚合的语法糖。如果糖不起作用,你需要回到更长的形式。

PIVOT语句中详细描述了<pivoted_table> ::= table_source PIVOT <pivot_clause> [ AS ] table_alias <pivot_clause> ::= ( aggregate_function ( value_column [ [ , ]...n ]) FOR pivot_column IN ( <column_list> ) ) 的语法:

aggregate_function

请注意,必须提供Class。 SQL Server中的所有聚合函数都可以对任意数量的输入值进行操作,并生成单个输出值。没有聚合可以产生多个输出值,正如您在此需要的那样。


这会给出您要求的结果,但确实依赖于每个m1值,m2declare @t table (Class char(2) not null,Member varchar(4) not null,Value int not null) insert into @t(Class,Member,Value) values ('c1','m1',10), ('c1','m2',20), ('c1','list',30), ('c1','list',40), ('c1','list',50), ('c2','m1',60), ('c2','m2',70), ('c2','list',80) select l.Class,m1.Value as m1,m2.Value as m2,l.Value as list from @t l inner join @t m1 on l.Class = m1.Class and m1.Member = 'm1' inner join @t m2 on l.Class = m2.Class and m2.Member = 'm2'where l.Member='list' 只有一行:

Class m1          m2          list
----- ----------- ----------- -----------
c1    10          20          30
c1    10          20          40
c1    10          20          50
c2    60          70          80

结果:

m1

如果 m2MAX的多行,而您只想要它们的m1值,那么您就可以我的上述查询子查询中的m2... inner join (select Class,MAX(Value) from @t where Member='m1' group by Class) m1 on l.Class = m1.Class ...

{{1}}

答案 1 :(得分:1)

SELECT  a.*, 
        b.Value
FROM    
        (
            SELECT  Class,
                    MAX(CASE WHEN Member = 'm1' THEN Value ELSE NULL END) [Member 1],
                    MAX(CASE WHEN Member = 'm2' THEN Value ELSE NULL END) [Member 2]
            FROM  tableName
            GROUP BY Class
        ) a 
        INNER JOIN
        (
            SELECT  Class, Value
            FROM    tableName 
            WHERE   Member = 'List'
        ) b ON a.Class = b.Class

RESULT

╔═══════╦══════════╦══════════╦═══════╗
║ CLASS ║ MEMBER 1 ║ MEMBER 2 ║ VALUE ║
╠═══════╬══════════╬══════════╬═══════╣
║ c1    ║       10 ║       20 ║    30 ║
║ c1    ║       10 ║       20 ║    40 ║
║ c1    ║       10 ║       20 ║    50 ║
║ c2    ║       60 ║       70 ║    80 ║
╚═══════╩══════════╩══════════╩═══════╝