postgreSQL -> Aggregate in where-Klausel
romy
- datenbank
Hi,
habe leider gerade feststellen müssen, dass in Aggregat-Funktionen nicht in der where-Klausel stehen dürfen. Wie könnte ich aber eine Abfrage dann machen?
Ich habe eine Tabelle rating in der zu verschiedenen Themen ratings sind.
zB.
tabelle rating
id | thema | rating
-------------------
1 | 1 | 10
2 | 1 | 8
3 | 2 | 9
4 | 1 | 7
5 | 2 | 8
6 | 2 | 10
normalerweise mache ich eine Abfrage mit avg(rating)
um Beispielsweise als Ergebnis dies zu bekommen:
thema2 : 9
thema1 : 8.333
jetzt möchte ich aber, dass wenn ratings zwischen 9 und 10 angezeigt werden sollen thema1 rausfällt.
Wie müsste ich jetzt die Abfrage gestalten?
ciao
romy
Moin Moin !
id | thema | rating
1 | 1 | 10
2 | 1 | 8
3 | 2 | 9
4 | 1 | 7
5 | 2 | 8
6 | 2 | 10normalerweise mache ich eine Abfrage mit avg(rating)
um Beispielsweise als Ergebnis dies zu bekommen:thema2 : 9
thema1 : 8.333
Mal ins Blaue geraten:
SELECT thema,AVG(rating.rating) as av_rating FROM rating GROUP BY thema WHERE av_rating >= 9
oder, etwas weniger effizient:
SELECT thema,AVG(rating.rating) as av_rating FROM rating GROUP BY thema HAVING av_rating >= 9
Ich finde es übrigens etwas ungeschickt, eine Tabellenspalte genauso zu nennen wie die Tabelle selbst.
Alexander
Hi Alexander,
SELECT thema,AVG(rating.rating) as av_rating FROM rating GROUP BY thema WHERE av_rating >= 9
*grumbl* ich hatte eigentlich versprochen es nicht wieder zu tun, oder
aber ich habe es auch gerade gesehen, sorry ;)
Ich finde es übrigens etwas ungeschickt, eine Tabellenspalte genauso zu nennen wie die Tabelle selbst.
ich hab nur Beispielsweise gearbeitet
Puh
ich werd wohl doch anfangen müssen Dir zu mailen, Filter oder nicht ;)
danke
ciao
romy
Moin Moin !
ich werd wohl doch anfangen müssen Dir zu mailen, Filter oder nicht ;)
Das hat man nun von seiner Hilfsbereitschaft!
Alexander
Hey,
Das hat man nun von seiner Hilfsbereitschaft!
na gut...ich lass es, ich brauch Dich schliesslich noch ;)
nämlich jetzt mit diesem Problem:
wenn ich jetzt die select-Abfrage einschränke, nehmen wir an, von=8, bis=10
nimmt er nicht wirklich den Durchschnitt, sondern je nach dem wie er noch angezeigt werden kann lässt er einfach ein oder zwei ratings weg:
Bsp:
id | thema | rating
-------------------
1 | 1 | 10
2 | 1 | 8
3 | 2 | 9
4 | 1 | 7
5 | 2 | 8
6 | 2 | 10
7 | 1 | 5
thema2 : 9
thema1 : 7.5
Abfrage: select avg(rating) as rating from rating where rating>=8 and rating <=10
sollte Eigentlich thema1 ausschliessen,aber:
er berechnet einfach 8.333 (d.h er nimmt das letzte rating weg)
wenn ich ab 9 rechne, lässt er die letzten 2 weg usw.
???
danke
romy
Moin Moin !
Hey,
Das hat man nun von seiner Hilfsbereitschaft!
na gut...ich lass es, ich brauch Dich schliesslich noch ;)Abfrage: select avg(rating) as rating from rating where rating>=8 and rating <=10
sollte Eigentlich thema1 ausschliessen,aber:
er berechnet einfach 8.333 (d.h er nimmt das letzte rating weg)
wenn ich ab 9 rechne, lässt er die letzten 2 weg usw.
Unglaublich, mit welcher gnadenlosen Konsequenz Du Dir in den Fuß schießt!
Welches "rating" soll die DB denn im WHERE-Teil nehmen ? Die Spalte "rating" oder den Alias "rating" als Abkürzung für "avg(rating)" ?
Ich weiß, was Du willst. Aber Deine DB nicht.
Nimm einen anderen Alias, und wenn es nur "rating1" ist.
Alexander
Hallo,
Abfrage: select avg(rating) as rating from rating where rating>=8 and rating <=10
GROUP BY vergessen?
SELECT thema, Avg(rating) AS MW_rating
FROM Tabelle2
GROUP BY thema
HAVING (((Avg(rating))>=8 And (Avg(rating))<=9));
Gruß
Axel
Moin Moin !
Du hast ja so recht. Möchtest Du den persönlichen Support für romy übernehmen? ;-)
Alexander
Hallo,
Du hast ja so recht. Möchtest Du den persönlichen Support für romy übernehmen? ;-)
Nö, ich will, wie jeder Egoist, nur auch wieder mal recht haben. Heute fehlte mir noch mein tägliches Erfolgserlebnis. *fg*
Gruß ;-)
Axel
Hi,
GROUP BY vergessen?
nein
HAVING (((Avg(rating))>=8 And (Avg(rating))<=9));
das hatte ich nicht, es hilft aber auch nicht
(kann mir mal bitte jemand den Sinn von having erklären???)
Problem ist das Gleiche.
Übrigens ohne Group By gibt es einen Syntaxfehler.
Ich würde ja mal dass Ganze Statement posten, aber ich glaube es ist gar nicht übersichtlich und jede Menge lang.
Well: here it comes
<schnipp>
SELECT u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdate, avg(sr.rating) AS rating, count(sr.rating) AS votes from userdata u, skin s, skinrating sr WHERE u.uid=s.uid AND s.activ='t' AND sr.skinid = s.skinid AND u.deleted='f' AND s.deleted='f' AND rating>=7 AND rating<=10 AND skdate>='2002-01-01' AND skdate<='2003-01-20' GROUP by u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdate HAVING (((Avg(sr.rating))>=7 And (Avg(sr.rating))<=10)) UNION SELECT u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdate, 0,0 FROM userdata u, skin s, skinrating sr WHERE u.uid=s.uid AND s.activ='t' AND u.deleted = 'f' AND s.deleted = 'f' AND skdate>='2002-01-01' AND skdate<='2003-01-20' AND not exists (SELECT * FROM skinrating sr WHERE sr.skinid = s.skinid) ORDER BY rating desc LIMIT 5 OFFSET 0
<schnapp>
Übrigens wollte ich den Alias verändern auf rating2 und da gab es einen Fehler, dass er ratings nicht kennt?
hm
was nun?
danke
romy
Moin Moin !
(kann mir mal bitte jemand den Sinn von having erklären???)
WHERE läuft durch einen "Query optimizer", der Unsinn ausfiltert und Redundanzen beseitigt und noch einige andere Sachen macht. Am Ende ist das Statement also oft schneller als beim Stumpf-und-Dumm-Ansatz.
HAVING ist drangeflickt, sprich: Erst wird das ganze Statement verarbeitet, dann erst filtert HAVING nach der Stumpf-und-Dumm-Methode alles aus, was nicht paßt. Das ist langsam, aber manchmal notwendig, gerade bei COUNT und GROUP BY.
<schnipp>
<schnapp>
Waaah! Das will ich nicht durchdenken.
Alexander
Hallo,
HAVING (((Avg(rating))>=8 And (Avg(rating))<=9));
das hatte ich nicht, es hilft aber auch nicht
(kann mir mal bitte jemand den Sinn von having erklären???)
http://www.postgresql.org/idocs/index.php?queries-table-expressions.html#QUERIES-GROUP
Well: here it comes
Puuh! Naja, ich wurde ja gewarnt. *g*
SELECT
u.surname,
u.name,
s.skinid,
s.skin,
s.screenshot,
s.skdate,
avg(sr.rating) AS MW_rating,
--- Bitte nicht rating (einen Feldnamen) als alias benutzen.
count(sr.rating) AS votes
from userdata u, skin s, skinrating sr
WHERE
u.uid=s.uid AND
s.activ='t' AND
sr.skinid = s.skinid AND
u.deleted='f' AND
s.deleted='f' AND
---
rating>=7 AND
rating<=10 AND
--- Hier schließt Du alle ratings <7 und >10 von der Gruppierung und damit auch von der Mittelwertberechnung aus. Diese Bedingungen bitte entfernen.
skdate>='2002-01-01' AND
skdate<='2003-01-20'
GROUP by u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdate
HAVING (((Avg(sr.rating))>=7 And (Avg(sr.rating))<=10))
---
Du willst, dass die _Mittelwerte_ zwischen 7 un 10 liegen!
---
UNION SELECT u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdate, 0,0 FROM userdata u, skin s, skinrating sr WHERE u.uid=s.uid AND s.activ='t' AND u.deleted = 'f' AND s.deleted = 'f' AND skdate>='2002-01-01' AND skdate<='2003-01-20' AND not exists (SELECT * FROM skinrating sr WHERE sr.skinid = s.skinid) ORDER BY rating desc LIMIT 5 OFFSET 0
---
Keine Ahnung, ob diese UNIONs noch richtig sind.
Puuh *gg*
Gruß
Axel
Was übersehen:
SELECT
u.surname,
u.name,
s.skinid,
s.skin,
s.screenshot,
s.skdate,
avg(sr.rating) AS MW_rating,
--- Bitte nicht rating (einen Feldnamen) als alias benutzen.count(sr.rating) AS votes
from userdata u, skin s, skinrating sr
WHERE
u.uid=s.uid AND
s.activ='t' AND
sr.skinid = s.skinid AND
u.deleted='f' AND
s.deleted='f' ANDrating>=7 AND
rating<=10 AND
--- Hier schließt Du alle ratings <7 und >10 von der Gruppierung und damit auch von der Mittelwertberechnung aus. Diese Bedingungen bitte entfernen.skdate>='2002-01-01' AND
skdate<='2003-01-20'
GROUP by u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdateHAVING (((Avg(sr.rating))>=7 And (Avg(sr.rating))<=10))
Du willst, dass die _Mittelwerte_ zwischen 7 un 10 liegen!
UNION SELECT u.surname, u.name, s.skinid, s.skin, s.screenshot, s.skdate, 0,0 FROM userdata u, skin s, skinrating sr WHERE u.uid=s.uid AND s.activ='t' AND u.deleted = 'f' AND s.deleted = 'f' AND skdate>='2002-01-01' AND skdate<='2003-01-20' AND not exists (SELECT * FROM skinrating sr WHERE sr.skinid = s.skinid)
---
Keine Ahnung, ob diese UNIONs noch richtig sind.
---
ORDER BY rating desc LIMIT 5 OFFSET 0
---Die Spalte rating gibt es gar nicht. Wonach soll er sortieren? Nach dem Mittelwert, nehme ich an.
---
ORDER BY Avg(sr.rating) desc LIMIT 5 OFFSET 0
---
Gruß
Axel
Hi,
danke nochmal,
also der Fehler lag wie schon fast gedacht im Detail. Nachdem ich die Where-Klausel, die eh schon im Having drin ist vorher herausgenommen habe und mein rating in rating2 umbenannt, war alles zu meiner Zufriedenheit.
ciao
romy
Hallo,
Mal ins Blaue geraten:
SELECT thema,AVG(rating.rating) as av_rating FROM rating GROUP BY thema WHERE av_rating >= 9
Bist Du sicher, dass ein WHERE _nach_ einem GROUP BY stehen darf?
Gruß
Axel
Moin Moin !
Nee. Aber wenn die DB es in der Reihenfolge nicht haben will, vertausche ich beide. Das geht schneller als in der Doku nachzulesen. ;-)
Alexander
Moin Moin !
Nee. Aber wenn die DB es in der Reihenfolge nicht haben will, vertausche ich beide. Das geht schneller als in der Doku nachzulesen. ;-)
Dann mein es aber was anderes. Dann gruppiert es ja nur die Datensätze, bei denen die Bedingung zutrifft ;-) Oder?
Gruß
Axel
Hi Axel
Dann mein es aber was anderes. Dann gruppiert es ja nur die Datensätze, bei denen die Bedingung zutrifft ;-) Oder?
Nein, dazu ist Having da:
http://aktuell.de.selfhtml.org/tippstricks/datenbanken/having/index.htm
Where darf nicht nach Group By stehen, das ist schlicht
und einfach nur ein Syntaxfehler.
Gruss Daniela
Hallo Daniela,
Dann meint es aber was anderes. Dann gruppiert es ja nur die Datensätze, bei denen die Bedingung zutrifft ;-) Oder?
Nein, dazu ist Having da:
Wozu ist HAVING da?
Alexander sagte, wenn er beim WHERE _nach_ dem GROUP BY eine Fehlermeldung bekommt, dann tauscht er die Reihenfolge einfach um, also WHERE _for_ GROUP BY. Das wäre einfacher, als jedesmal ins Handbuch zu sehen. Daraufhin schrieb ich: -> siehe oben.
Where darf nicht nach Group By stehen, das ist schlicht
und einfach nur ein Syntaxfehler.
Sach ich doch! [pref:t=35548&m=194022]
Gruß ;-)
Axel