平均

2011-09-09 74 views
15

我称之为表请求和数据的模样:平均

Req_ID R1 R2 R3 R4 R5 

R12673 2 5 3 7 10 
R34721 3 5 2 1 8 
R27835 1 3 8 5 6 

现在我想显示R1,R2,R3,R4和R5的平均

所以我写了一个查询如:

Select Req_ID, Avg(R1+R2+R3+R4+R5) as Average 
from Request 
Group by Req_ID 

但我只是得到了R1,R2,R3,R4和R5的总和不是平均值吗?我在哪里做错了。

+1

AVG适用于行,而不能在列。你期望答案是什么? –

回答

14

如果数据被存储为INT,你可能想尝试

Average = (R1 + R2 + R3 + R4 + R5)/5.0 
+1

R1,R2,R3,R4和R5都是真实数据类型 – Peter

+1

请记住,NULL值可能是一个问题。 Check @ martin-smith解决方案 – Jaider

+0

@Jaider那么3.2和NULL的平均值是多少?除非另有说明,否则我会期望NULL的结果。 –

3

你可以简单地做:

Select Req_ID, (avg(R1)+avg(R2)+avg(R3)+avg(R4)+avg(R5))/5 as Average 
from Request 
Group by Req_ID 

,对吗?

我假设你可能具有相同REQ_ID多行并在这些情况下,您需要使用具有相同REQ_ID来计算所有列和行的平均对那些行

+0

@beetree Req_ID在表 – Peter

+0

@Aaron Bertrand中是唯一的我不知道这是OP想要什么,但我没有看到GROUP BY不能在那里的语法原因... –

+0

哦,但是如果Req_ID在表格中是独一无二的,为什么你有集团呢?没有道理......? – beetree

21

你不提,如果列可以为空。如果他们和你想的一样的语义的AVG合计为您提供可以做(2008)

SELECT *, 
     (SELECT AVG(c) 
     FROM (VALUES(R1), 
         (R2), 
         (R3), 
         (R4), 
         (R5)) T (c)) AS [Average] 
FROM Request 

2005年的版本是

SELECT *, 
     (SELECT AVG(c) 
     FROM (SELECT R1 
       UNION ALL 
       SELECT R2 
       UNION ALL 
       SELECT R3 
       UNION ALL 
       SELECT R4 
       UNION ALL 
       SELECT R5) T (c)) AS [Average] 
FROM Request 
+0

Martin Smith - 您能否在您提供的解决方案中解释T(c)'''的意义? –

+0

@AlokShenoy T是派生表的别名,c是其单列的别名。 –

+0

啊!谢谢你的解释。 –

4

在PostgreSQL,多一点乏味获得的平均一行中的多个(2到8)列只定义了一组名为average()的七个函数。将产生非空列的平均值。

然后就是

select *,(r1+r2+r3+r4+r5)/5.0,average(r1,r2,r3,r4,r5) from request; 
req_id | r1 | r2 | r3 | r4 | r5 |  ?column?  |  average 
--------+----+----+----+----+----+--------------------+-------------------- 
R12673 | 2 | 5 | 3 | 7 | 10 | 5.4000000000000000 | 5.4000000000000000 
R34721 | 3 | 5 | 2 | 1 | 8 | 3.8000000000000000 | 3.8000000000000000 
R27835 | 1 | 3 | 8 | 5 | 6 | 4.6000000000000000 | 4.6000000000000000 
(3 rows) 

update request set r4=NULL where req_id='R34721'; 
UPDATE 1 

select *,(r1+r2+r3+r4+r5)/5.0,average(r1,r2,r3,r4,r5) from request; 
req_id | r1 | r2 | r3 | r4 | r5 |  ?column?  |  average 
--------+----+----+----+----+----+--------------------+-------------------- 
R12673 | 2 | 5 | 3 | 7 | 10 | 5.4000000000000000 | 5.4000000000000000 
R34721 | 3 | 5 | 2 | | 8 |     | 4.5000000000000000 
R27835 | 1 | 3 | 8 | 5 | 6 | 4.6000000000000000 | 4.6000000000000000 
(3 rows) 

select *,(r3+r4+r5)/3.0,average(r3,r4,r5) from request; 
req_id | r1 | r2 | r3 | r4 | r5 |  ?column?  |  average 
--------+----+----+----+----+----+--------------------+-------------------- 
R12673 | 2 | 5 | 3 | 7 | 10 | 6.6666666666666667 | 6.6666666666666667 
R34721 | 3 | 5 | 2 | | 8 |     | 5.0000000000000000 
R27835 | 1 | 3 | 8 | 5 | 6 | 6.3333333333333333 | 6.3333333333333333 
(3 rows) 

像这样:

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC, 
V3 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    IF V3 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V3; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC, 
V3 NUMERIC, 
V4 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    IF V3 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V3; END IF; 
    IF V4 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V4; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC, 
V3 NUMERIC, 
V4 NUMERIC, 
V5 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    IF V3 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V3; END IF; 
    IF V4 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V4; END IF; 
    IF V5 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V5; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC, 
V3 NUMERIC, 
V4 NUMERIC, 
V5 NUMERIC, 
V6 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    IF V3 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V3; END IF; 
    IF V4 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V4; END IF; 
    IF V5 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V5; END IF; 
    IF V6 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V6; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC, 
V3 NUMERIC, 
V4 NUMERIC, 
V5 NUMERIC, 
V6 NUMERIC, 
V7 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    IF V3 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V3; END IF; 
    IF V4 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V4; END IF; 
    IF V5 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V5; END IF; 
    IF V6 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V6; END IF; 
    IF V7 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V7; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 

CREATE OR REPLACE FUNCTION AVERAGE (
V1 NUMERIC, 
V2 NUMERIC, 
V3 NUMERIC, 
V4 NUMERIC, 
V5 NUMERIC, 
V6 NUMERIC, 
V7 NUMERIC, 
V8 NUMERIC) 
RETURNS NUMERIC 
AS $FUNCTION$ 
DECLARE 
    COUNT NUMERIC; 
    TOTAL NUMERIC; 
BEGIN 
    COUNT=0; 
    TOTAL=0; 
    IF V1 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V1; END IF; 
    IF V2 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V2; END IF; 
    IF V3 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V3; END IF; 
    IF V4 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V4; END IF; 
    IF V5 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V5; END IF; 
    IF V6 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V6; END IF; 
    IF V7 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V7; END IF; 
    IF V8 IS NOT NULL THEN COUNT=COUNT+1; TOTAL=TOTAL+V8; END IF; 
    RETURN TOTAL/COUNT; 
    EXCEPTION WHEN DIVISION_BY_ZERO THEN RETURN NULL; 
END 
$FUNCTION$ LANGUAGE PLPGSQL; 
+0

这可能是我会做的。存储过程似乎比长查询更紧凑,更易于阅读。 – krishnab