根据列获得平均值?

时间:2014-07-17 22:55:43

标签: sql

我有一个查询,我获得每行的平均值并显示员工。 我希望它显示每位员工的平均值。意思是我想平均所有与同一员工的行。

我怎样才能做到这一点?

这是我目前的查询:

SELECT 
(
    SELECT AVG(rating)
    FROM (VALUES 
        (cast(c.rating1 as Float)), 
        (cast(c.rating2 as Float)), 
        (cast(c.rating3 as Float)), 
        (cast(c.rating4 as Float)), 
        (cast(c.rating5 as Float))
    ) AS v(rating)
    WHERE v.rating > 0
) avg_rating, employee
From CSEReduxResponses c
Where 
     month(c.approveddate)= 6
AND  year(c.approveddate)=2014

下面我有一些我创建的示例数据:

 create table CSEReduxResponses (rating1 int, rating2 int, rating3 int, rating4 int, rating5 int,
                                approveddate datetime,employee int)

insert into CSEReduxResponses (rating1 , rating2  ,rating3 , rating4 , rating5 ,
                                approveddate, employee )
values 
(5,4,5,1,4,'2014-06-18',1),
(5,4,5,1,4,'2014-06-18',1),
(5,4,5,1,0,'2014-06-18',1),
(5,4,0,1,4,'2014-06-18',2),
(5,4,5,1,4,'2014-06-18',2),
(5,4,0,1,4,'2014-06-18',3),
(5,0,5,4,4,'2014-06-18',3),
(5,4,5,0,0,'2014-06-18',3);

3 个答案:

答案 0 :(得分:0)

这样的事情怎么样?

select employee,
       avg(case when n.n = 1 and rating1 > 0 then rating1
                when n.n = 2 and rating2 > 0 then rating2
                when n.n = 3 and rating3 > 0 then rating3
                when n.n = 4 and rating4 > 0 then rating4
                when n.n = 5 and rating5 > 0 then rating5
           end)
from CSEReduxResponses c cross join
     (select 1 as n union all select 2 union all select 3 union all select 4 union all select 5
     ) n
where month(c.approveddate)= 6 and year(c.approveddate)=2014
group by employee;

我建议将where子句重写为:

where c.approveddate >= '2014-06-01' and c.approveddate < '2014-07-01'

这将允许SQL引擎在approveddate上使用索引。

答案 1 :(得分:0)

select 
(sum(rating1)+sum(rating2)+sum(rating3)+sum(rating4)+sum(rating5))
/
(count(nullif(rating1,0))+count(nullif(rating2,0))+count(nullif(rating3,0))+count(nullif(rating4,0))+count(nullif(rating5,0))) 
as avg_rating,
count(*) as number_of_responses, employee 
From CSEReduxResponses where month(approveddate)= 6 AND year(approveddate)=2014 group by employee ; 

答案 2 :(得分:0)

我还想出了一个使用UDF的稍微光滑的版本。我更喜欢这个,因为平均函数可能对其他查询有用...

DELIMITER //
DROP FUNCTION IF EXISTS cca_wip.avg_ignore0//
CREATE FUNCTION cca_wip.avg_ignore0(
  str VARCHAR(500)
) RETURNS double
    COMMENT 'values separated by a coma, that are to be averaged. 0 will be treated as NULL'

BEGIN
  DECLARE ss TEXT;
  DECLARE sum, count double;

IF length(str)=0 or str not regexp '[0-9]' then RETURN 0;
end if;

IF str regexp '[a-z]' then RETURN NULL;
end if;

SET str=replace(str,'NULL','0');
SET sum =0;
SET count =0;

WHILE length(str)>0 DO
    set ss=substring_index(str,',',1);
    SET sum = sum + ss;

    IF ss>0 THEN SET count = count+1;
    END IF;

    set str=trim(trim(trim(',') from trim(trim(ss from str))));
END WHILE;

RETURN (sum/count);
END//

DELIMITER ;

select
avg_ignore0(group_concat(concat_ws(',',rating1,rating2,rating3,rating4,rating5))),
count(*)  as number_of_responses, 
employee
From CSEReduxResponses
where 
month(approveddate)= 6 AND  year(approveddate)=2014
group by employee ;