我怎样才能使用PIVOT来显示其细胞的平均和计数?

时间:2011-01-24 12:50:30

标签: sql sql-server-2005 oracle pivot

syntax我得到了强烈的印象,PIVOT不支持为单元格计算单个聚合函数以外的任何东西。

从统计视​​图中显示一些平均值而不给出平均值所指的案例数量非常不满意(这是礼貌版本)。

是否有一些很好的模式来评估基于avg和pivotots的基于计数的枢轴并将它们混合在一起以产生一个好的结果?

3 个答案:

答案 0 :(得分:3)

是的,您需要使用旧样式cross tabPIVOT只是语法糖,它解决了几乎相同的方法。

SELECT AVG(CASE WHEN col='foo' THEN col END) AS AvgFoo,
       COUNT(CASE WHEN col='foo' THEN col END) AS CountFoo,...

如果你有很多聚合,你总是可以使用CTE

WITH cte As
(
SELECT CASE WHEN col='foo' THEN col END AS Foo...
)
SELECT MAX(Foo),MIN(Foo), COUNT(Foo), STDEV(Foo)
FROM cte

答案 1 :(得分:1)

在其细胞中同时..所以你的意思是在同一个单元格内,因此作为varchar?

您可以在使用数据透视表之前计算聚合查询中的平均值和计数值,并将它们作为文本连接在一起。

这里PIVOT运算符的作用只是将行转换为列,并且只使用某些聚合函数(例如MAX / MIN),因为语法需要它 - 您预先计算的aggregate query每个旋转列只有一个值。

修改

遵循bernd_k的oracle / mssql解决方案,我想指出在SQL Server中执行此操作的另一种方法。它需要将多列简化为一列。

SELECT MODULE,
  modus + '_' + case which when 1 then 'AVG' else 'COUNT' end AS modus,
  case which when 1 then AVG(duration) else COUNT(duration) end AS value
FROM test_data, (select 1 as which union all select 2) x
GROUP BY MODULE, modus, which

SELECT *
FROM (
 SELECT MODULE,
  modus + '_' + case which when 1 then 'AVG' else 'COUNT' end AS modus,
  case which when 1 then CAST(AVG(1.0*duration) AS NUMERIC(10,2)) else COUNT(duration) end AS value
 FROM test_data, (select 1 as which union all select 2) x
 GROUP BY MODULE, modus, which
) P
PIVOT (MAX(value) FOR modus in ([A_AVG], [A_COUNT], [B_AVG], [B_COUNT])
) AS pvt
ORDER BY pvt.MODULE

在上面的示例中,AVG和COUNT是兼容的(count - int => numeric)。如果不是,请将两者明确转换为兼容类型。

注 - 由于整数平均,第一个查询将M2 / A的AVG显示为2。第二个(透视)查询显示考虑小数的实际平均值。

答案 2 :(得分:1)

Oracle 11g +解决方案:

create table test_data (
    module varchar2(30),
    modus   varchar2(30),
    duration Number(10)
);


insert into test_data values ('M1', 'A', 5); 
insert into test_data values ('M1', 'A', 5); 
insert into test_data values ('M1', 'B', 3); 
insert into test_data values ('M2', 'A', 1); 
insert into test_data values ('M2', 'A', 4); 


select   *
FROM (
select   *
from test_data
) 
PIVOT (
    AVG(duration) avg , count(duration) count
    FOR modus in ( 'A', 'B')
) pvt
ORDER BY pvt.module;

我不喜欢包含撇号的列名,但结果包含我想要的内容:

MODULE                            'A'_AVG  'A'_COUNT    'B'_AVG  'B'_COUNT
------------------------------ ---------- ---------- ---------- ----------
M1                                      5          2          3          1
M2                                    2.5          2                     0

我真的很想知道微软男孩们在枢轴中只允许一个聚合功能时做了什么。我称评估平均值没有伴随计数统计谎言

SQL-Server 2005 + (基于Cyber​​wiki):

CREATE TABLE test_data (
    MODULE VARCHAR(30),
    modus   VARCHAR(30),
    duration INTEGER
);


INSERT INTO test_data VALUES ('M1', 'A', 5); 
INSERT INTO test_data VALUES ('M1', 'A', 5); 
INSERT INTO test_data VALUES ('M1', 'B', 3); 
INSERT INTO test_data VALUES ('M2', 'A', 1); 
INSERT INTO test_data VALUES ('M2', 'A', 4); 


SELECT MODULE, modus, ISNULL(LTRIM(STR(AVG(duration))), '') + '|' + ISNULL(LTRIM(STR(COUNT(duration))), '') RESULT
FROM test_data
GROUP BY MODULE, modus;

SELECT   *
FROM (
SELECT MODULE, modus, ISNULL(LTRIM(STR(AVG(duration))), '') + '|' + ISNULL(LTRIM(STR(COUNT(duration))), '') RESULT
FROM test_data
GROUP BY MODULE, modus
) T
PIVOT (
 MAX(RESULT)
 FOR modus in ( [A], [B])
) AS pvt
ORDER BY pvt.MODULE

结果:

MODULE                         A                     B
------------------------------ --------------------- ---------------------
M1                             5|2                   3|1
M2                             2|2                   NULL