2017-10-17 1 views
0

enter image description hereSQL Gruppierung gemittelt

Hallo! Ich bin neu in SQL Ich habe Probleme mit der Verwendung der AVG und Summe Funktion. Ich arbeite mit der obigen Datenbank. Ich brauche den durchschnittlichen Gewinn für jeden Filmstar zu finden, aber nur dann ausgegeben, die nur im Durchschnitt, wenn die Summe ihrer Gewinne ist> 200.

SELECT MovieStar.sname, avg(profit) From MovieStar, Movie 
GROUP BY sname 
HAVING sum(Movie.profit) > 200 

Ich verwende SQL Fiddle, um zu versuchen und dies herauszufinden, aber es scheint, um den Durchschnittswert der GANZE Gewinnspalte zurückzugeben und nicht jeden Schauspieler, aber ich bin mir nicht sicher, was ich falsch machen könnte. Wie kann ich das angehen, so dass ich den Mittelwert jedes einzelnen Akteurs und nicht den Mittelwert der gesamten Gewinnspalte ermitteln kann? Here ist die SQL Fiddle, die ich gemacht habe. Danke im Voraus!

+0

Sie sollten Gruppe auch von dem Schauspieler? Wenn Sie nur laufende Durchschnittswerte verwenden, sehen Sie sich auch die Fensterfunktionen an. –

+0

ist das nicht, was "GROUP BY sname" tut? Gruppiere sie mit dem Namen? – helloworld

+0

Sie haben keine Join-Bedingung, noch ein aktuelles modernes JOIN; also wird jeder Stern mit ** jedem ** Film gepaart. – Uueerdo

Antwort

3

Sieht so aus, als ob die Abfrage eine CROSS JOIN-Operation ausführt, ein kartesisches Produkt, das jeden Film mit jedem moviestar vergleicht. Scheint so, als würden wir nur einen Moviestar bestimmten Filmen zuordnen wollen, wahrscheinlich mit (einschließlich) der starsin Tabelle, um die Matches zu bekommen.

Ich empfehle Ihnen, den Old-School-Komma-Operator die Join-Operation abzuziehen. Verwenden Sie stattdessen das neuere JOIN-Schlüsselwort. Und setzen Sie die Join-Prädikate in die entsprechende ON-Klausel anstelle der WHERE-Klausel.

Best Practice ist auch zu qualifizieren alle Spalte Referenzen; selbst wenn es nicht erforderlich ist, Mehrdeutigkeiten zu beseitigen, verhindert es, dass die Abfrage bricht, wenn neue Spalten hinzugefügt werden, und es hilft dem zukünftigen Leser ... der armen Seele, die die Tabellendefinitionen betrachten muss, um herauszufinden, welche Spalten von welchen Tabellen kommen .

Ich glaube, Sie so etwas wie dies wollen:

SELECT ms.sname 
-- , ms.sno 
     , AVG(m.profit) AS avg_profit 
-- , SUM(m.profit) AS tot_profit 
    FROM MovieStar ms 
    JOIN StarsIn si 
     ON si.sno = ms.sno 
    JOIN Movie m 
     ON m.mno = si.mno 
    GROUP BY ms.sno, ms.sname 
    HAVING SUM(m.profit) > 200 
    ORDER BY AVG(m.profit) DESC 
+0

Dies ist genau der Grund, warum der implizite Join vermieden werden sollte, da Sie [versehentlich einen Cross-Join ausführen können] (https://Stackoverflow.com/a/317465/1422451) wie OP. – Parfait

+0

Vielen Dank an Sie beide! Ich wusste nicht, dass Cross-Join-Operationen so passieren könnten, aber das macht Sinn. Kann ich fragen, warum Sie in dieser Situation ON anstelle von WHERE gewählt haben? In meinem Kopf wirken sie wie das Gleiche oder zumindest eng verwandt. – helloworld

+0

Ich ziehe es vor, die Bedingungen für die Zeile "Matching" in die ON-Klausel zu setzen und andere Bedingungen in die WHERE-Klausel aufzunehmen. Dies ist keine Voraussetzung, MySQL kümmert es nicht. Dies ist nur eine Stilkonvention, eine Präferenz. Ich denke, es ist einfacher für den Leser, wenn die Abfrage acht Tabellen verbindet, die Bedingungen in der ON-Klausel zu haben, anstatt den Leser alle Bedingungen in der WHERE-Klausel durchgehen zu lassen. Die Bedingungen in der ON-Klausel machen es auch leichter, wenn wir OUTER JOINS machen. – spencer7593