使用SQL Server 2008 R2的数据透视表查询中的聚合函数

时间:2014-09-13 06:36:28

标签: sql sql-server sql-server-2008 pivot-table

我有一张如下所示的表格,详情如下:

CREATE TABLE testrf
(
  cola INTEGER,
  colb VARCHAR(10)
)   

插入一些数据:

INSERT INTO testrf VALUES(1,'x')  
INSERT INTO testrf VALUES(1,'x')
INSERT INTO testrf VALUES(2,'x')
INSERT INTO testrf VALUES(3,'y')
INSERT INTO testrf VALUES(4,'y')
INSERT INTO testrf VALUES(5,'c')
INSERT INTO testrf VALUES(6,'c')
INSERT INTO testrf VALUES(7,'c')
INSERT INTO testrf VALUES(8,'d')
INSERT INTO testrf VALUES(3,'y')
INSERT INTO testrf VALUES(12,'M1')
INSERT INTO testrf VALUES(13,'L1')
INSERT INTO testrf VALUES(14,'C2')
INSERT INTO testrf VALUES(1,'c')
INSERT INTO testrf VALUES(1,'d')
INSERT INTO testrf VALUES(1,'L1')


SELECT * FROM testrf;

cola   colb
------------
1       x
1       x
2       x
3       y
4       y
5       c
6       c
7       c
8       d
3       y
1       c
1       d
12      M1
13      L1
14      C2
1       L1

现在我想为我编写查询的上述数据显示数据透视表:

 DECLARE @cols NVARCHAR(MAX)
 DECLARE @SQL NVARCHAR(MAX)

 SELECT  @cols = STUFF ( (SELECT DISTINCT '],[' + v.colb                        
               FROM testrf AS v                                         
FOR XML PATH('')), 1, 2, '') + ']'   


SET @SQL = N'SELECT cola,TotalGroups,AvailableIn,'+ @cols +'
   FROM                     
   (SELECT  v.cola,v.colb,(select count(distinct colb) from testrf) TotalGroups,c.AvailableIn
       FROM testrf AS v  
       inner join
       (select cola,count(case when colb>=1 then 1 else 0 end) AS AvailableIn FROM testrf
       group by cola) c 
       on c.cola = v.cola                                                                                                  
    ) p                     
       PIVOT                
           (            
               count(colb)                        
               FOR colb IN ( '+ @cols + ' )                        
           ) AS pvt';      

    EXEC(@SQL)     

我会得到这个:

 cola TotalGroups AvailableIn  c    C2  d   L1  M1  x   y
 ----------------------------------------------------------
 1       7            5        1    0   1   1   0   2   0
 2       7            1        0    0   0   0   0   1   0
 3       7            2        0    0   0   0   0   0   2
 4       7            1        0    0   0   0   0   0   1
 5       7            1        1    0   0   0   0   0   0
 6       7            1        1    0   0   0   0   0   0
 7       7            1        1    0   0   0   0   0   0
 8       7            1        0    0   1   0   0   0   0
 12      7            1        0    0   0   0   1   0   0
 13      7            1        0    0   0   1   0   0   0
 14      7            1        0    1   0   0   0   0   0

注意:请注意row number 1 and 3。在AvailableIn列中,第1行的值为5,其中列的可用值为4,仅c,d,L1,x其余为零。还有第3行,其中AvailableIn为2,其中列的可用值仅为1 y。我想我被aggregate function置于pivot query内。

SQL小提琴 - > http://sqlfiddle.com/#!3/d1acc/8

2 个答案:

答案 0 :(得分:1)

如果colb大于1(你的所有字母都是),那么你需要colb

的独特列表(就像在父查询中一样)

这是我做的唯一改变:

(select cola,count(distinct colb) AS AvailableIn FROM testrf

Fiddle

答案 1 :(得分:1)

你确定有问题吗?

INSERT INTO testrf VALUES(1,'x');
INSERT INTO testrf VALUES(1,'x');
...
INSERT INTO testrf VALUES(1,'c');
INSERT INTO testrf VALUES(1,'d');
INSERT INTO testrf VALUES(1,'L1');

That is 5 references to ColA = 1

c    C2  d   L1  M1  x   y
1    0   1   1   0   2   0  << adds to 5

我会在您的查询中添加一些建议

  1. 使用QUOTENAME()而不是硬编码[]括号。
  2. ColB是Varchar所以不要使用WHEN ColB&gt; = 1,使用COLB&gt; ='1'
  3. COUNT()为每个非空值添加一个,因此不要在计数内使用else 0

    DECLARE @cols NVARCHAR(MAX), @SQL NVARCHAR(MAX)
    
    SELECT  @cols = STUFF ( (SELECT DISTINCT ',' + QUOTENAME(v.colb)                        
                   FROM testrf AS v                                         
    FOR XML PATH('')), 1, 1, '') 
    
    
    SET @SQL = N'SELECT cola,TotalGroups,AvailableIn,'+ @cols +'
       FROM                     
       (SELECT  v.cola,v.colb,(select count(distinct colb) from testrf) TotalGroups,c.AvailableIn
           FROM testrf AS v  
           inner join
           (select cola,count(case when colb>=''1'' then 1 end) AS AvailableIn FROM testrf
           group by cola) c 
           on c.cola = v.cola                                                                                                  
        ) p                     
           PIVOT                
               (            
                   count(colb)                        
                   FOR colb IN ( '+ @cols + ' )                        
               ) AS pvt'    
    
    EXEC(@SQL)