2011-09-09 15 views
15

ho una tabella chiamata richiesta ei dati si presenta come:media di più colonne

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 

Ora voglio visualizzare la media di R1, R2, R3, R4 e R5

Così ho scritto una query come:

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

Ma ottengo solo la somma di R1, R2, R3, R4 e R5 non la media? Dove sto sbagliando?

+1

AVG funziona su file, e non tra le colonne. Cosa ti aspetti che la risposta sia? –

risposta

14

Se i dati sono memorizzati come INT, si consiglia di provare

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

R1, R2, R3, R4 e R5 sono tutti di tipo di dati reali – Peter

+1

Ricordare che i valori di 'NULL' potrebbero essere un problema. Controlla la soluzione @ martin-smith – Jaider

+0

@Jaider quindi qual è la media di 3.2 e NULL? Mi aspetterei un risultato di NULL a meno che i requisiti espliciti non siano specificati diversamente. –

3

Si potrebbe semplicemente fare:

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

Destra?

sto supponendo che si può avere più righe con lo stesso REQ_ID e in questi casi si vuole calcolare la media di tutte le colonne e le righe per le righe con la stessa REQ_ID

+0

@beetree Req_ID è univoco nella tabella – Peter

+0

@Aaron Bertrand Non so se è ciò che l'OP vuole, concesso, ma non vedo ragioni sintattiche che GROUP BY non può essere lì ... –

+0

Oh, ma se Req_ID è unico nella tabella perché hai il gruppo? Non ha senso ...? – beetree

21

Tu non parlare se le colonne sono annullabili. Se sono e si desidera la stessa semantica che l'aggregato AVG prevede che si può fare (2008)

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

La versione 2005 è un po 'più noioso

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 - vorresti spiegare il significato di '' 'T (c)' '' nella soluzione che hai fornito? –

+0

@AlokShenoy T è l'alias della tabella derivata ec l'alias della sua singola colonna. –

+0

Ah! Grazie per la spiegazione. –

4

In PostgreSQL, per ottenere la media di più colonne (da 2 a 8) in una riga definiscono semplicemente un insieme di sette funzioni chiamate average(). Produrrà la media delle colonne non nulle.

E poi basta

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) 

Ti piace questa:

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

Questo è probabilmente quello che vorrei fare. Le stored procedure sembrano molto più compatte e più facili da leggere rispetto a una lunga query. – krishnab