Chrisi: MySQL Order By etwas komplizierter

Hallo zusammen,

ich sitze gerade an einer SQL Abfrage und komme nicht zu dem Ergebnis das ich benötige.

Ich hole aus einer MySQL Datenbank in der Kapazitäten für Veranstaltungen gespeichert werden Daten und sortiere anhand der Menge der eingetragenen Kapazitäten (unten heissen die freedays) durch.

Nun soll die Abfrage erweitert werden um "special" Einträge, jeder Spezial Eintrag soll bei der Sortierung immer ganz oben stehen, ohne Rücksicht auf Kapazitäten. Dazu habe ich die Tabelle in der die Veranstaltungen gespeichert werden um eine Spalte "special" erweitert, ist diese Spalte mit 1 belegt ist es ein special Eintrag, falls 0 nicht.

Meine Abfrage sieht so aus:

SELECT objekte.*,COUNT(kalender.day) AS freedays FROM kalender,objekte GROUP BY objekte.id ORDER BY objekte.special DESC, freedays DESC

Er holt mir jetzt schön meine objekte aus der Datenbank und sortiert mir diese anhand von special und dannach dann nochmal nach der Anzahl der freien Kapazitäten.

Nun sieht das Ergebnis leider so aus das die special Einträge nicht ganz oben stehen sondern immer nur als erster unter den Datensätzen die die gleiche Menge an freedays haben, ist natürlich von der Logik her richtig aber nicht der Effekt den ich benötige :)

Nun meine Frage: Muss ich 2 getrennte Abfragen machen um die special Einträge von normalen trennen zu können ?

Oder gibt es vieleicht eine Möglichkeit bei Order BY eine Priorität festzulegen, so dass ich mehr Gewicht auf die Sortierung von special legen kann ?

Danke für jeden Tipp und viele Grüße, Chrisi ...

  1. yo,

    SELECT objekte.*,COUNT(kalender.day) AS freedays FROM kalender,objekte GROUP BY objekte.id ORDER BY objekte.special DESC, freedays DESC

    Nun sieht das Ergebnis leider so aus das die special Einträge nicht ganz oben stehen sondern immer nur als erster unter den Datensätzen die die gleiche Menge an freedays haben, ist natürlich von der Logik her richtig aber nicht der Effekt den ich benötige :)

    alleine von der ORDER BY Klausel betrachtet funktioniert das so, wie du es haben willst, sprich er würde erst alle specials auflisten und dann erst die Kapazitäten berücksichtigen. insofern würde deine specials mit den eintrag 1 immer vor den datensätzen mit den eintrag 0 stehen.

    dein problem ist allen anschein nach ein anderes, nämlich das GROUP BY in der abfrage. normalerweise sind nur spalten in der ausgabe einer abfrage bei der verwendung von GROUP BY erlaubt, die auch in der GROUP BY klausel stehen, bzw. die aggregat-funtkionen sind. ansonsten würde das dbms eine fehlermeldung ausgeben. mysql geht da aber leider einen anderen weg und die folge ist, dass viele immer wieder in diese falle tappen. ich tippe mal, die falsche sortierung ist ein folgeproblem davon.

    Ilja

    1. Hi Ilja,

      dein problem ist allen anschein nach ein anderes, nämlich das GROUP BY in der abfrage.

      Danke für Deine Hilfe.

      Es lag tatsächlich daran das ich kalender.day mit COUNT() gezählt habe aber nicht in der GROUP BY Klausel hatte, nun schauts so aus "GROUP BY objekte.id,kalender.day" ...

      Eigentlich lusitg, ich habe den Satz mit der Info "http://dev.mysql.com/doc/mysql/de/group-by-functions.html" noch vor dem Posting gelesen, aber nicht verstanden :)

      Hätte aber auch nicht gedacht das sich das ganze so auf die Sortierung auswirkt.

      Viele Grüße, Chrisi ...

    2. Hi Ilja,

      ich glaube ich war da zu schnell mit meinen Erfolgserlebnissen :)

      Das ganze klappt so doch nicht GROUP BY kalender.day,objekte.id, leider fasst er mir die einzellnen Objekte mit der Abfrage nicht mehr zusammen, dadurch gibt es dann jedes Objekt so oft wie es Tage in der DB gibt ...

      Lasse ich dann wieder die Gruppierung bei den Tagen weg zählt er falsch und die ganze Sortierung ist hin :)

      Weist du vieleicht wie ich das ganze geschickter lösen kann ? Bzw. geht das überhaupt ?

      Danke und viele Grüße, Chrisi ...

      1. yo,

        ich glaube ich war da zu schnell mit meinen Erfolgserlebnissen :)

        hääte mich auch gewundert ;-)

        Weist du vieleicht wie ich das ganze geschickter lösen kann ? Bzw. geht das überhaupt ?

        GROUP BY ist nicht ganz so trivial anzuwenden und wie man dein problem hängt von zwei dingen ab. zum einen, welches dbms du benutzt (denke mal mysql) aber dann auch welche version. und zum anderen, ob du uns mitteilst, wie deine tabellen aufgebaut sind, und was genau du angezeigt haben willst. mit * is das nämlich schwer zu ersehen...

        Ilja

        1. Hi Ilja,

          problem hängt von zwei dingen ab. zum einen ...

          MySQL 4.0.15-Max, meine Tabellen schaun so aus:

          Tabelle Objekte: OID, objektname, spezial
          -> OID Integer Primary Key
          -> objektname enthält den Objektnamen
          -> spezial ist 0 oder 1 und legt fest ob ein Objekt "Premiumeintrag" ist

          Tabelle Kalender: KID, OID, day
          -> KID Integer Primary Key
          -> OID Integer Schlüssel für das Objekt in Tab Objekte
          -> day Y-m-d, Datum des verfuegbaren Tages

          Nun soll die Abfrage mir die Objekdaten (OID,objektname) zurückgeben die in der Tabelle Kalender für die nächsten 14 Tage einen Eintrag haben, dass ganze soll dann nach der Anzahl der gefundenen Tage und der Option "spezial" sortiert werden.

          Also wer die meisten freien innerhalb der nächsten 14 Tage (Kalender.day<=DATE_ADD(CURDATE(), INTERVAL 14 DAY)) hat soll ganz oben stehen, hat aber ein Eintrag weniger Tage und ist Premium muss er in der Sortierung drüber stehen.

          Also: Erst grenze ich die Tage ein, dann zähle ich die gefundenen Tage durch und sortiere Anhand der Menge, dann soll nochmal sortiert werden um die "Premiumeinträge" nach oben zu schieben ...

          Ich hoffe das kommt noch verständlich rüber, ich kann das schlecht in Worte fassen :)

          Viele Grüße und danke, Chrisi ...

          1. yo,

            SELECT o.OID, o.objektname, COUNT (*) AS Freedays
            FROM Objekte AS o, Kalender AS k
            WHERE o.oid = k.oid
            AND k.day BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 14 DAY))
            GROUP BY o.OID, o.objektname
            ORDER BY o.spezial DESC, Freedays DESC

            Ilja

            1. yo,

              AND k.day BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 14 DAY))

              da ist eine klammer zuviel am ende....

              Ilja

            2. Hi Ilja,

              danke für deine Hilfe, mit deiner Abfrage klappt es wunderbar und gelernt habe ich auch was :)

              Viele Grüße, Chrisi ...