2011-09-09 42 views
15

Tengo una tabla llamada de solicitud y los datos se parece a:promedio de varias columnas

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 

Ahora quiero mostrar el promedio de R1, R2, R3, R4 y R5

Así que escribió una consulta como:

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

Pero apenas consigo la suma de R1, R2, R3, R4 y R5 no la media? Donde estoy haciendo mal

+1

AVG trabaja en filas, no a través de las columnas. ¿Cuál esperas que sea la respuesta? –

Respuesta

14

Si los datos se almacenan como INT, es posible que desee probar

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

R1, R2, R3, R4 y R5 todos son de tipo de datos real – Peter

+1

Tenga en cuenta que los valores 'NULL' podrían ser un problema. Compruebe la solución @ martin-smith – Jaider

+0

@Jaider ¿cuál es el promedio de 3.2 y NULL? Esperaría un resultado de NULL a menos que se indique lo contrario. –

3

Usted podría simplemente hacer:

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

derecho?

Asumo que usted puede tener varias filas con el mismo REQ_ID y en estos casos si desea calcular la media de todas las columnas y filas de las filas con el mismo REQ_ID

+0

@beetree Req_ID es único en la tabla – Peter

+0

@ Aaron Bertrand No sé si es lo que desea el OP, pero no veo ninguna razón sintáctica por la que GROUP BY no pueda estar allí ... –

+0

Oh, pero si Req_ID es único en la tabla ¿por qué tienes el Grupo? No tiene sentido ...? – beetree

21

Usted no menciona si las columnas son nulables. Si son y que quieren la misma semántica que el agregado AVG ofrece que puede hacer (2008)

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

La versión 2005 es un poco más tediosa

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 - ¿podría explicar la importancia de '' 'T (c)' '' en la solución que ha proporcionado? –

+0

@AlokShenoy T es el alias de la tabla derivada yc el alias de su columna individual. –

+0

¡Ah! Gracias por la explicación. –

4

En PostgreSQL, para obtener el promedio de Las columnas múltiples (de 2 a 8) en una fila solo definen un conjunto de siete funciones llamadas promedio(). Producirá el promedio de las columnas no nulas.

Y a continuación, sólo

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) 

De esta manera:

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

Esto es probablemente lo que yo haría. Los procedimientos almacenados parecen mucho más compactos y fáciles de leer que una consulta larga. – krishnab