[Sql] muss in der GROUP BY-Klausel vorkommen oder in einer Aggregatfunktion verwendet werden



Answers

In Postgres können Sie auch die spezielle Syntax DISTINCT ON (expression) :

SELECT DISTINCT ON (cname) 
    cname, wmname, avg
FROM 
    makerar 
ORDER BY 
    cname, avg DESC ;
Question

Ich habe eine Tabelle, die aussieht wie dieser Anrufer 'makerar'

 cname  | wmname |          avg           
--------+-------------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

Und ich möchte das maximale avg für jeden cname auswählen.

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

aber ich werde einen Fehler bekommen,

ERROR:  column "makerar.wmname" must appear in the GROUP BY clause or be used in an   aggregate function 
LINE 1: SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

also mache ich das

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname, wmname;

Dies führt jedoch nicht zu den beabsichtigten Ergebnissen, und die unten angegebene falsche Ausgabe wird angezeigt.

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

Tatsächliche Ergebnisse sollten sein

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

Wie kann ich dieses Problem beheben?

Hinweis: Diese Tabelle ist eine VIEW, die aus einer vorherigen Operation erstellt wurde.




Dies scheint auch zu funktionieren

SELECT *
FROM makerar m1
WHERE m1.avg = (SELECT MAX(avg)
                FROM makerar m2
                WHERE m1.cname = m2.cname
               )



Das Problem bei der Angabe von nicht gruppierten und nicht aggregierten Feldern in einer group by selects besteht darin, dass die Engine nicht wissen kann, welches Feld dieses Datensatzes in diesem Fall zurückgegeben werden soll. Ist es zuerst? Ist es das letzte? In der Regel gibt es keinen Datensatz, der dem aggregierten Ergebnis entspricht (Ausnahmen sind min und max ).

Es gibt jedoch eine Problemumgehung: Machen Sie das erforderliche Feld auch aggregiert. In posgres sollte das funktionieren:

SELECT cname, (array_agg(wmname ORDER BY avg DESC))[1], MAX(avg)
FROM makerar GROUP BY cname;

Beachten Sie, dass dies ein Array aller wnames erstellt, geordnet nach avg, und das erste Element zurückgibt (Arrays in Postgres sind 1-basiert).




Links