2011-09-09 2 views
15

Mam tabeli o nazwie Zapytanie a dane wygląda następująco:Średnia z wielu kolumn

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 

Teraz chcę wyświetlić średnią z R1, R2, R3, R4 i R5

więc napisałem zapytanie takie jak:

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

Ale po prostu otrzymuję sumę R1, R2, R3, R4 i R5 nie średnią? Gdzie robię źle.

+1

AVG działa na wiersze, a nie w poprzek kolumn. Jakiej odpowiedzi oczekujesz? –

Odpowiedz

14

Jeśli dane są przechowywane jako INT, może chcesz spróbować

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

R1, R2, R3, R4 i R5 wszystkie mają prawdziwy typ danych. – Peter

+1

Należy pamiętać, że wartości "NULL" mogą być problemem. Sprawdź @ martin-smith rozwiązanie – Jaider

+0

@Jaider, więc jaka jest średnia 3,2 i NULL? Spodziewam się wyniku o wartości NULL, chyba że wyraźnie określono inne wymagania. –

3

Można po prostu zrobić:

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

prawo?

jestem przy założeniu, że można mieć wiele wierszy z tym samym Req_ID iw tych przypadkach chcesz obliczyć średnią we wszystkich kolumn i wierszy dla tych wierszy o tej samej Req_ID

+0

@beetree Req_ID jest unikalny w tabeli – Peter

+0

@Aaron Bertrand Nie wiem, czy to jest to, co OP chce, przyznane, ale nie widzę powodu syntaktycznego, że GROUP BY nie może być tam ... –

+0

Oh, ale jeśli Req_ID jest wyjątkowy w tabeli, dlaczego masz Grupę? Czy to nie ma sensu ...? – beetree

21

Nie wspominając o ile kolumny są zerowe. Jeśli są one i chcesz te same semantykę że łączna AVG zapewnia można robić (2008)

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

Wersja 2005 jest nieco bardziej uciążliwe

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 - czy mógłbyś wyjaśnić znaczenie '' 'T (c)' '' w rozwiązaniu, które podałeś? –

+0

@AlokShenoy T jest aliasem wyprowadzonej tabeli i c aliasem pojedynczej kolumny. –

+0

Ah! Dziękuję za wyjaśnienie. –

4

W PostgreSQL, aby uzyskać średnio wiele (2 do 8) kolumn w jednym wierszu definiuje tylko zestaw siedmiu funkcji zwanych średnią(). Wytworzy średnią z niezerowych kolumn.

A potem po prostu

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) 

Jak to:

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

To jest prawdopodobnie to, co bym zrobił. Przechowywane procedury wydają się dużo bardziej kompaktowe i łatwiejsze do odczytania niż długie zapytanie. – krishnab