Durchschnitt einer Zeile berechnen

master100

Benutzer
Beiträge
5
Hallo Zusammen,

ich würde gerne den Durschnitt einer Zeile Berechnen. Mein Problem ist das nicht jede Zeile einen Wert enthält und die Abfrage nur funktioniert sofern jede Zelle in einer Zeile gefüllt ist.

Nr. Spalte 1 Spalte 2 Spalte 3
1 4 2 7
2 0 1 2
3 3 9

SELECT (Spalte 1 + Spalte 2+ Spalte 3) / 3 FROM tabelle GROUP Nr;

Hat jemand ein Tipp??

Vielen Dank
Mit freundlichen Grüßen
master100
 
Werbung:
Hi.

Auf die schnelle wäre das eine Möglichkeit:
Code:
SELECT (
CASE WHEN spalte1 THEN spalte1 ELSE 0 END + 
CASE WHEN spalte2 THEN spalte2 ELSE 0 END + 
CASE WHEN spalte2 THEN spalte2 ELSE 0 END)
/ 3 AS avg
FROM tabelle

Gruß
Hony
 
Die Frage ist natürlich auch noch: sollen Spalten mit NULL überhaupt beachtet werden?

Eigentlich keine Frage, denn bei der normalen avg() - Funktion werden NULL-Werte ignoriert. Nun denn, frisch ans Werk:

Code:
test=*# create table xyz2 (i1 int, i2 int, i3 int);
CREATE TABLE
Time: 20,766 ms
test=*# insert into xyz2 values (100, null, 100);
INSERT 0 1
Time: 0,331 ms
test=*# insert into xyz2 values (100, 300, null);
INSERT 0 1
Time: 0,140 ms
test=*# insert into xyz2 values (1000, null, null);
INSERT 0 1
Time: 0,159 ms
test=*# create or replace function array_avg(int[]) returns float as $$begin return avg(unnest) from (select * from unnest($1))foo; end; $$language plpgsql;
CREATE FUNCTION
Time: 0,571 ms
test=*# select array_avg(array[i1,i2,i3]) from xyz2;
 array_avg
-----------
  100
  200
  1000
(3 rows)

Hab mir also eine extra array_avg() - Funktion geschrieben, die ein int[] - Array bekommt und daraus korrekt avg berechnet. Beim Select übergebe ich die fraglichen Spalten an die Funktion, wobei ich da in einem Schritt ein Array draus baue. Voila!

PostgreSQL, also nicht mit MySQL, M$SQL oder anderen Dialekten 1:1 umsetzbar.
 
Also nur um NULL-Werte zu Fitern braucht man keine CASE-Schleife, das geht mit isnull()
Code:
SELECT    ( isnull(spalte1,0) + isnull(spalte2,0) ) / anzahl
FROM    tabelle
Die Frage, ob NULL und ob 0 Werte gezählt werden sollen ist natürlich berechtigt, dazu könnte man dann die CASE Schleife nutzen. Je nachdem über wieviele Spalten wir hier reden ist das eine oder das andere vieleicht eleganter.
 
Also nur um NULL-Werte zu Fitern braucht man keine CASE-Schleife, das geht mit isnull()
Code:
SELECT    ( isnull(spalte1,0) + isnull(spalte2,0) ) / anzahl
FROM    tabelle
Die Frage, ob NULL und ob 0 Werte gezählt werden sollen ist natürlich berechtigt, dazu könnte man dann die CASE Schleife nutzen. Je nachdem über wieviele Spalten wir hier reden ist das eine oder das andere vieleicht eleganter.

Du mußt auch noch die Anzahl beachten, falls es korrekt sein und NULL nicht beachtet werden soll. ;-)
 
Das habe ich ja geschrieben. Die Frage ist ob hier immder der Durchschnitt aller Spalten oder der Durchschnitt aller vorhandenen Werte ermittelt werden soll. Wenn ersteres, finde ich die CASE-Schleife von Hony% unnötig aber man könnte die z.B. zur Ermittlung der der Anzahl der Werte verwenden.
 
Hallo Zusammen,

danke für die schnellen Antworten.
Die Zellen in dennen kein Wert ist sprich NULL sollen irgnoriert werden.
Es soll lediglich von 4 Zeilen der Durchschnitt berechnet werden.
In der Tabelle werden Bewertungen dargestellt. die Bewertungen gehen von 0 bis 10 Punkte.

Es gibt vier Spalten mit Bewertungen für ein Produkt und hierfür würde ich gerne den Durchschnitt berechnen.

Gruß master100
 
Keine Ahnung ob es unter MSSQL so oder ähnlich laufen würde. Der einfachste Weg wäre hier vermutlich isnull() in Verbindung mit der CASE-Schleife von Honey%
Code:
SELECT    ( isnull(spalte1,0) + isnull(spalte2,0) + isnull(spalte3,0) + isnull(spalte4,0) ) /
        (    CASE
            WHEN    spalte1
            THEN    1
            ELSE    0
            END +
            CASE
            WHEN    spalte2
            THEN    1
            ELSE    0
            END +
            CASE
            WHEN    spalte3
            THEN    1
            ELSE    0
            END +
            CASE
            WHEN    spalte4
            THEN    1
            ELSE    0
            END ) AS avg
FROM    tabelle
Sofern wir hier tatsächlich von 4 Spalten und nicht 4 Zeilen reden.
 
Wenn ich mich hier anschließen darf? Ich bekomme aus einer SELECT-Anfrage eine Reihe von Ergebniszeilen. In der letzten Spalte habe ich einen Prozentwert errechnet, basierend auf eine Auftrags- und Bestandsmenge. Ich würde nun gern über diese Ergebniszeilen in der letzten Spalte den durchschnittl. Prozentwert anzneigen, über alle Ergebniszeilen. WIE bekommt man das hin?!

Aktuelle Abfrage
Code:
SELECT
    Auftragsnr,
    Artikelnr,
    Artikelname,
    Menge,
    CASE
        WHEN Bestand > Menge
            THEN 100
            ELSE 100/Menge * Bestand
    END AS Ergebnis
  
FROM
    Aufträge

WHERE
    Auftragsnr = 'xyz'

Ergebnis aktuell:
Code:
1       xyz       22222       Artikel A       5       80%
2       xyz       33333       Artikel B       2       100%
3       xyz       44444       Artikel C       4       100%
4       xyz       55555       Artikel D       8       50%

Ich würde in der letzten Spalte nun gern den durchschnittl. Prozentwert haben -> 82,5%
 
In etwa so:

Code:
SELECT    Auftragsnr,
        Artikelnr,
        Artikelname,
        Menge,
        (    CASE
            WHEN    Bestand > Menge
            THEN    100
            ELSE    100/Menge * Bestand
            END ) AS Ergebnis
FROM    Aufträge
WHERE    Auftragsnr = 'xyz'
UNION ALL
SELECT    NULL AS Auftragsnr,
        NULL AS Artikelnr,
        'Summe' AS Artikelname,
        sum(Menge) AS Menge,
        sum(    CASE
                WHEN    Bestand > Menge
                THEN    100
                ELSE    100/Menge * Bestand
                END ) / count(1) AS Ergebnis
FROM    Aufträge
WHERE    Auftragsnr = 'xyz'
 
Das funktioniert irgendwie nicht. Ich wollte auch nicht eine SUMMEN-Zeile unterhalb der Ergebnisse, sondern der entsprechende Wert soll (wiederholend) in der letzten Spalte stehen. Dort wo jetzt die CASE-Abfrage ist. Als Wert hatte ich bei Deiner Abfrage auch 111,... als Ergebnis, müsste aber 82,5 sein.
 
Werbung:
Das mit 111 kann ich nicht wirklich erklären, da dürfte eigentlich nur 82,5 raus kommen sofern wir hier wirklich die 4 Ergebnisszeilen zurück kiregen und keine mit NULL Werten oder so. In eine Spalte kriegst du den Wert entweder über einen Join oder über einen Subselect. Ich denke mal der Join ist schneller:
Code:
SELECT   Auftragsnr,
     Artikelnr,
     Artikelname,
     Menge,
     (   CASE
       WHEN   Bestand > Menge
       THEN   100
       ELSE   100/Menge * Bestand
       END ) AS Ergebnis
FROM   Aufträge
CROSS JOIN (   SELECT   sum(
             (   CASE
               WHEN   Bestand > Menge
               THEN   100
               ELSE   100 / Menge * Bestand
               END )
             ) / count(1) AS Ergebnis
         FROM   Aufträge
         WHERE   Auftragsnr = 'xyz' ) t
WHERE   Auftragsnr = 'xyz'
 
Zurück
Oben