romy: postgreSQL -> Aggregate in where-Klausel

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

--
DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
->Alles ist gut wenn es aus Schokolade ist
  1. Moin Moin !

    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

    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

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
    1. 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

      --
      DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
      ->Alles ist gut wenn es aus Schokolade ist
      1. Moin Moin !

        ich werd wohl doch anfangen müssen Dir zu mailen, Filter oder nicht ;)

        Das hat man nun von seiner Hilfsbereitschaft!

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
        1. 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

          --
          DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
          ->Alles ist gut wenn es aus Schokolade ist
          1. 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

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
          2. 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

            1. Moin Moin !

              Du hast ja so recht. Möchtest Du den persönlichen Support für romy übernehmen? ;-)

              Alexander

              --
              Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
              1. 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

            2. 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

              --
              DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
              ->Alles ist gut wenn es aus Schokolade ist
              1. 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

                --
                Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
              2. 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

                1. 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' 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)

                  ---
                  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

                  1. 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

                    --
                    DIE ROMY AUS L. AN DER P. SAGT DANKE UND AUF WIEDERSEHEN
                    ->Alles ist gut wenn es aus Schokolade ist
    2. 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

      1. 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

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
        1. 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

          1. 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

            --
            Nein, wir frieren unsere Hühner nicht auf Gletschern fest.
            1. 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